Question

Can I use Jackson instead of JSON-lib with Groovy's HTTPBuilder when setting the body on request?

Example:

client.request(method){
      uri.path = path
      requestContentType = JSON

      body = customer

      response.success = { HttpResponseDecorator resp, JSONObject returnedUser ->

        customer = getMapper().readValue(returnedUser.content[0].toString(), Customer.class)
        return customer
      }
}

In this example, I'm using Jackson fine when handling the response, but I believe the request is using JSON-lib.

Was it helpful?

Solution

Yes. To use another JSON library to parse incoming JSON on the response, set the content type to ContentType.TEXT and set the Accept header manually, as in this example: http://groovy.codehaus.org/modules/http-builder/doc/contentTypes.html. You'll receive the JSON as text, which you can then pass to Jackson.

To set JSON encoded output on a POST request, just set request body as a string after you've converted it with Jackson. Example:

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.1' )

import groovyx.net.http.*

new HTTPBuilder('http://localhost:8080/').request(Method.POST) {
    uri.path = 'myurl'
    requestContentType = ContentType.JSON
    body = convertToJSONWithJackson(payload)

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

Also note that when posting, you have to set the requestContentType before setting the body.

OTHER TIPS

Instead of manually setting headers and calling the method with the wrong ContentType as suggested in the accepted answer, It would be cleaner and easier to overwrite the parser for application/json.

def http = new HTTPBuilder()
http.parser.'application/json' = http.parser.'text/plain'

This will cause JSON responses to be handled in the same manner that plain text is handled. The plain text handler gives you an InputReader along with the HttpResponseDecorator. To use Jackson to bind the response to your class, you just need to use an ObjectMapper:

http.request( GET, JSON ) {

    response.success = { resp, reader ->
        def mapper = new ObjectMapper()
        mapper.readValue( reader, Customer.class )
    }
}

Quite late to the party, but now you can do this in a cleaner way, specially in places with too many HTTP calls, e.g. in tests (example is for Spock):

def setup() {
    http = configure {
        request.uri = "http://localhost:8080"
        // Get your mapper from somewhere
        Jackson.mapper(delegate, mapper, [APPLICATION_JSON])
        Jackson.use(delegate, [APPLICATION_JSON])
        response.parser([APPLICATION_JSON]) { config, resp ->
            NativeHandlers.Parsers.json(config, resp)
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top