SimonTheLeg SimonTheLeg - 3 months ago 33
Groovy Question

Groovy HTTP Builder: Catching invalid formatted JSON response

Hi I'm using Groovy HTTPBuilder to make a POST call similar like this:

http.request( POST, JSON ) { req ->
body = [name:'testName', title:'testTitle']
response.success = { resp, json ->
println resp.statusLine
println json
}
}


However due to a Bug (which I cannot solve myself), the REST server returns a JSON that is not correctly formatted resulting in the following exception when my application is trying to parse it:

groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object

I'm fairly new to groovy closures and HTTPBuilder, but is there a way to make the application check if the JSON is actually valid before parsing it and returning null if so?

Answer

I'm not sure this is a good idea, but it is possible to supply your own JSON parser, which facilitates the original request. It also affords the opportunity to "fix" the JSON if the known bug can be fixed.

Example below. The parser is essentially the same code that HTTPBuilder uses, with the exception of a hard-coded charset of UTF-8.

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

import groovy.json.*

import groovyx.net.http.*
import static groovyx.net.http.Method.*
import static groovyx.net.http.ContentType.*

def url = "http://localhost:5150/foobar/bogus.json"

def http = new HTTPBuilder(url)

http.parser."application/json" = { resp ->
    println "tracer: custom parser"
    def text = new InputStreamReader( resp.getEntity().getContent(), "UTF-8");
    def result = null
    try {
        result = new JsonSlurper().parse(text)
    } catch (Exception ex) {
        // one could potentially try to "fix" the JSON here if
        // there is a known bug in the server
        println "warn: custom parser caught exception"
    }

    return result
}

http.request( POST, JSON ) { req ->
    body = [name:'testName', title:'testTitle']
     response.success = { resp, json ->
        println resp.statusLine
        println json
    }
}