2011-07-26 109 views
10

我发现this doc关于如何使用HttpBuilder发布JSON数据。我对此很陌生,但这是一个非常直接的例子,很容易遵循。这是代码,假设我已经导入了所有必需的依赖关系。现在使用Groovy的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) 

异常我错过了什么?我将不胜感激您的任何帮助。

回答

15

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

大部分POST examples here都在构建器中设置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}" 
    } 
} 
+0

谢谢你的回应,但仍然没有很好:( 的java.lang .NullPointerExceptionat groovyx.net.http.HTTPBuilder $ RequestConfigDelegate.setBody(HTTPBuilder.java:1147) 你是否在你的机器上试过这个例子?它是否工作? 另外,关于uri.path的值,它是否需要成为现有的路径? –

+0

看起来你走得更远;新的NPE是当它试图找到适当的响应处理程序。请求可能失败了,所以你需要一个失败处理程序。我会更新我的例子。 –

+0

*“关于uri.path的值,它是否需要成为现有路径”* - 如果主机不存在,您将得到某种连接错误。如果它确实存在,但是您发布的资源不存在,您将获得HTTP 404或其他内容。 –

0

我在Grails应用程序(至少POST)放弃了HTTPBuilder和所使用的方法sendHttps提供here

(记住,如果你正在使用一个Grails应用的直Groovy的以外,对德的技术/编码JSON会有所不同,以低于)

只是application/json在更换内容类型的sendHttps()

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 
} 
1

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

这不是公认的答案,但它对我有用。您可能需要在指定“body”属性之前设置内容类型。这对我来说似乎很愚蠢,但它就是这样。你也可以使用'send contentType,[attrs]'语法,但是我发现单元测试更加困难。希望这有助于(迟到)!

8

我前段时间遇到同样的问题,发现一个博客指出'requestContentType'应该放在'body'之前。从那以后,我在每个httpBuilder方法中都添加了注释'Set ConentType before body or risk null pointer'。

这里是我会建议为你的代码的变化:

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}" 
    } 
} 

干杯!

+0

唯一的问题,如果我尝试将对象作为JSON发布,它将空字符串放在空字符串字段上,但我确实需要空值 – dmitryvim

+0

嗨dmitryvim, 你在说POST请求的响应JSON吗?或者你是否试图将正文JSON中的字符串字段设置为null? – Robert

2

如果您需要执行与JSON的contentType一个POST,并通过一个复杂的JSON数据,尝试你的身体手动转换:

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 -> } 
}