Fork me on GitHub

LD.

Music, software, life… and stuff.

[ Twitter ] [ GitHub ] [ Linked In ]

Using Grails’s JSON support with HTTPBuilder

I am currently working on a set of JSON over HTTP web services APIs between Grails applications. Producing JSON content in Grails applications is ridiculously trivial, but the story on consuming content is not so clear.

I am using Tom Nichol’s HTTPBuilder for consumption. It’s a great library, but does take a little getting used to. Fortunately, the documentation is excellent.

HTTPBuilder ships with JSON support based on Andres Almiray’s json-lib. That works fine, but I was worried about a potential impedance mismatch between json-lib’s encoding/decoding and Grails’.

Here’s how I configured HTTPBuilder to use Grails’ JSON bits for encoding/decoding JSON data…

import groovyx.net.http.HTTPBuilder
import groovyx.net.http.ParserRegistry
import groovyx.net.http.ContentType.JSON

import org.apache.http.entity.EntityTemplate
import org.apache.http.entity.ContentProducer
import org.apache.http.message.BasicHeader

// create a builder instance
def builder = new HTTPBuilder()

// the closure that takes a HttpServletResponse and returns an object
def jsonParser = { response ->
    grails.converters.JSON.parse(new InputStreamReader(response.entity.content, ParserRegistry.getCharset(response)))
}

// the closure that takes an object and returns an org.apache.http.HttpEntity
def jsonEncoder = { value ->
    def json = value instanceof Closure ? new grails.web.JSONBuilder().build(value) : new grails.converters.JSON(value)
    def producer = [writeTo: { OutputStream out -> out.withWriter { json.render(it) } }] as ContentProducer
    def entity = new EntityTemplate(producer)
    entity.contentType = new BasicHeader("Content-Type", JSON.toString())
    entity
}

// for each JSON content type, install the handler
JSON.contentTypeStrings.each {
    builder.parser."$it" = jsonParser
    builder.encoder."$it" = jsonEncoder
}

Note that you have to configure each created HTTPBuilder instance.

Here is some contrived example usage. We are calling a JSON “mirror” service that simply just returns the JSON it was sent.


import grails.plugin.spock.*

import groovyx.net.http.Method.POST
import groovyx.net.http.ContentType.JSON

class HttpBuilderWithGrailsJsonSpec extends UnitSpec {

    void "test it all works like it should"() {
        given: "a configured HTTP builder"
        def builder = new HTTPBuilder("http://jsonmirror.org")
        // configure the builder as per above
        
        when: "I post '{a: 1}' to the JSON mirror service"
        def requestMethod = POST
        def responseContentType = JSON
        def result = builder.request(requestMethod, responseContentType) {
            def requestContentType = JSON
            send(requestContentType) {
                a = 1
            }
        }
        
        then: "I get the JSON '{a: 1}' returned"
        result.a == 1
    }
}

Posted: Feb 25th, 2010 @ 1:01 pm

Tags: #software  #grails  

Comments

Archive · RSS · Theme by Autumn