使用Groovy的HTTPBuilder发布JSON数据

13

我在stackoverflow上找到了这篇文档,讲述了如何使用HttpBuilder发布JSON数据。虽然我是新手,但这个例子非常简单易懂。假设我已经导入了所有必要的依赖项,以下是示例代码:

def http = new HTTPBuilder( 'http://example.com/handler.php' )
http.request( POST, JSON ) { req ->
    body = [name:'bob', title:'construction worker']

     response.success = { resp, json ->
        // response handling here
    }
}

现在我的问题是,我遇到了一个异常

java.lang.NullPointerException
    at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1131)

我有什么遗漏吗?非常感谢您能提供的任何帮助。


答案似乎已经过时了;答案中提到的导入项已不再存在;要了解如何在Groovy中发布JSON数据,请尝试访问以下链接:https://dev59.com/w18e5IYBdhLWcg3wfaYy - jmarina
5个回答

18

我查看了HttpBuilder.java:1131,猜测在该方法中检索到的内容类型编码器为null。

这里的大多数POST示例在生成器中设置requestContentType属性,这似乎是代码用于获取该编码器的方式。尝试像这样设置:

import groovyx.net.http.ContentType

http.request(POST) {
    uri.path = 'http://example.com/handler.php'
    body = [name: 'bob', title: 'construction worker']
    requestContentType = ContentType.JSON

    response.success = { resp ->
        println "Success! ${resp.status}"
    }

    response.failure = { resp ->
        println "Request failed with status ${resp.status}"
    }
}

谢谢您的回复,但仍然不好:( java.lang.NullPointerException at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1147) 您是否尝试在您的计算机上运行该示例?它可以工作吗?此外,在uri.path的值上,它需要是现有的路径吗? - Chris Laconsay
看起来你已经走得更远了;新的 NPE 是在尝试查找适当的响应处理程序时出现的。请求可能失败了,所以你需要一个失败处理程序。我会更新我的示例。 - Rob Hruska
“在uri.path的值上,它需要是一个现有的路径吗?” - 如果主机不存在,您将会得到某种连接错误。如果它确实存在,但您要POST的资源不存在,则会收到HTTP 404或类似的响应。 - Rob Hruska
它对我起作用了。我在groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1200)处遇到了一个NPE,通过添加requestContentType得以解决。谢谢。 - acorello
唯一的问题是,如果我尝试将对象作为JSON发布,它会在空字符串字段上放置空字符串,但我确实需要null。 - dmitryvim
显示剩余2条评论

8

我之前遇到了同样的问题,后来找到一篇博客指出应该在“body”之前设置“requestContentType”。从那时起,我在每个httpBuilder方法中都添加了注释“在body之前设置ConentType,否则可能会出现空指针”的注释。

以下是我建议你对代码进行的更改:

import groovyx.net.http.ContentType

http.request(POST) {
    uri.path = 'http://example.com/handler.php'
    // Note: Set ConentType before body or risk null pointer.
    requestContentType = ContentType.JSON
    body = [name: 'bob', title: 'construction worker']

    response.success = { resp ->
        println "Success! ${resp.status}"
    }

    response.failure = { resp ->
        println "Request failed with status ${resp.status}"
    }
}

欢呼!

唯一的问题是,如果我尝试将对象作为JSON发布,它会在空字符串字段上放置空字符串,但我确实需要null。 - dmitryvim
嗨dmitryvim, 你是在谈论POST请求的响应JSON吗?还是你试图将JSON主体中的字符串字段设置为null? - Robert

2
如果您需要执行一个带有contentType JSON并传递复杂json数据的POST请求,请尝试手动转换请求体:
def attributes = [a:[b:[c:[]]], d:[]] //Complex structure
def http = new HTTPBuilder("your-url")
http.auth.basic('user', 'pass') // Optional
http.request (POST, ContentType.JSON) { req ->
  uri.path = path
  body = (attributes as JSON).toString()
  response.success = { resp, json -> }
  response.failure = { resp, json -> }
}    

1

我在这篇文章中找到了答案:POST with HTTPBuilder -> NullPointerException?

虽然不是被采纳的答案,但对我很有用。在指定“body”属性之前,您可能需要设置内容类型。这对我来说似乎很愚蠢,但事实就是如此。您也可以使用“send contentType,[attrs]”语法,但我发现它更难进行单元测试。希望这能帮到你(尽管有些晚)!


-1

我在我的Grails应用程序中放弃了HTTPBuilder(至少是POST),并使用这里提供的sendHttps方法。

(请记住,如果您在Grails应用程序之外使用纯Groovy,则解码/编码JSON的技术将与下面的技术不同)

只需在sendHttps()的以下行中替换内容类型为application/json即可。

httpPost.setHeader("Content-Type", "text/xml")
...
reqEntity.setContentType("text/xml")

您还需要负责将您的JSON数据进行编组

 import grails.converters.*

 def uploadContact(Contact contact){  
   def packet = [
      person : [
       first_name: contact.firstName,
       last_name: contact.lastName,
       email: contact.email,
       company_name: contact.company
      ]
   ] as JSON //encode as JSON
  def response = sendHttps(SOME_URL, packet.toString())
  def json = JSON.parse(response) //decode response 
  // do something with json
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接