Groovy HTTPBuilder在解析有效的json时产生错误

时间:2014-09-06 21:37:27

标签: json groovy

我是Groovy新手并尝试从groovy脚本连接到GitHub API但是当HTTPBuilder尝试解析JSON响应时,我收到一个奇怪的错误。

我的简单脚本如下

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.2' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

def apiToken = '[api_token]'

def http = new HTTPBuilder( 'https://api.github.com/' )

// perform a GET request, expecting JSON response data
http.request( GET, JSON ) {

  uri.path = '/orgs/octokit/repos'
  headers.'Accept' = 'application/json'
  headers.'Authorization' = 'Basic ' + (apiToken + ':').bytes.encodeBase64().toString()
  headers.'User-Agent' = '[username]'

  // response handler for a success response code:
  response.success = { resp, json ->
    println resp.statusLine
  }

  // handler for any failure status code:
  response.failure = { resp ->
    println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
  }
}

但是当解析JSON时,我得到以下错误

Sep 06, 2014 10:21:54 PM groovyx.net.http.HTTPBuilder$1 handleResponse
WARNING: Error parsing 'application/json; charset=utf-8' response
groovy.json.JsonException: expecting '}' or ',' but got current char '"' with an int value of 34

The current character read is '"' with an int value of 34
expecting '}' or ',' but got current char '"' with an int value of 34
line number 1
index number 256
[{"id":417862,"name":"octokit.rb","full_name":"octokit/octokit.rb","owner":{"login":"octokit","id":3430433,"avatar_url":"https://avatars.githubusercontent.com/u/3430433?v=2","gravatar_id":"43f38795089d56a2a7092b7d0c71fa76","url":"h
................................................................................................................................................................................................................................................................^
    at groovy.json.internal.JsonParserCharArray.complain(JsonParserCharArray.java:162)
    at groovy.json.internal.JsonParserCharArray.decodeJsonObject(JsonParserCharArray.java:152)
    at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:196)
    at groovy.json.internal.JsonParserCharArray.decodeJsonObject(JsonParserCharArray.java:140)
    at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:196)
    at groovy.json.internal.JsonParserCharArray.decodeJsonArray(JsonParserCharArray.java:346)
    at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:192)
    at groovy.json.internal.JsonParserCharArray.decodeValue(JsonParserCharArray.java:166)
    at groovy.json.internal.JsonParserCharArray.decodeFromChars(JsonParserCharArray.java:45)
    at groovy.json.internal.JsonParserCharArray.parse(JsonParserCharArray.java:409)
    at groovy.json.internal.BaseJsonParser.parse(BaseJsonParser.java:121)
    at groovy.json.JsonSlurper.parse(JsonSlurper.java:224)
    at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:280)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1207)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1074)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
    at groovy.lang.Closure.call(Closure.java:423)
    at groovy.lang.Closure.call(Closure.java:439)
    at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:560)
    at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:489)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:515)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:434)
    at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:383)
    at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
    at sprint-snapshot.run(sprint-snapshot.groovy:11)
    at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:258)
    at groovy.lang.GroovyShell.run(GroovyShell.java:502)
    at groovy.lang.GroovyShell.run(GroovyShell.java:491)
    at groovy.ui.GroovyMain.processOnce(GroovyMain.java:650)
    at groovy.ui.GroovyMain.run(GroovyMain.java:381)
    at groovy.ui.GroovyMain.process(GroovyMain.java:367)
    at groovy.ui.GroovyMain.processArgs(GroovyMain.java:126)
    at groovy.ui.GroovyMain.main(GroovyMain.java:106)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:106)
    at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128)

Caught: groovyx.net.http.ResponseParseException: OK
groovyx.net.http.ResponseParseException: OK
    at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:495)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1070)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:1044)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:515)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:434)
    at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:383)
    at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
    at sprint-snapshot.run(sprint-snapshot.groovy:11)
Caused by: groovy.json.JsonException: expecting '}' or ',' but got current char '"' with an int value of 34

The current character read is '"' with an int value of 34
expecting '}' or ',' but got current char '"' with an int value of 34
line number 1
index number 256
[{"id":417862,"name":"octokit.rb","full_name":"octokit/octokit.rb","owner":{"login":"octokit","id":3430433,"avatar_url":"https://avatars.githubusercontent.com/u/3430433?v=2","gravatar_id":"43f38795089d56a2a7092b7d0c71fa76","url":"h
................................................................................................................................................................................................................................................................^
    at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:280)
    at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:560)
    at groovyx.net.http.HTTPBuilder$1.handleResponse(HTTPBuilder.java:489)
    ... 7 more

该错误似乎表明无效的JSON,但我已经确认响应确实有效,正如您对Github API所期望的那样。

更奇怪的是,如果我删除了授权'完全标头并发送请求未经验证,它工作正常:S

4 个答案:

答案 0 :(得分:3)

最新版本的Groovy存在问题。我遇到过同样的问题。您的代码应该与2.3.0之前的Groovy版本一起使用。 (可选)您可以为HTTPBuilder尝试不同的默认JSONParserType。

请参阅 http://beta.groovy-lang.org/docs/groovy-2.3.0/html/gapi/groovy/json/JsonSlurper.html http://alfonsorv.com/instruct-groovy-httpbuilder-to-handle-a-json-response-with-wrong-content-type/

答案 1 :(得分:2)

这是我的代码解决方法

    /*
     * Normally we would use the method "request(GET, JSON)" to return a json result, but with the release
     * of groovy 2.3.0, which included extensive changes to JSON parsing, the result returned from the
     * Artifactory REST API call 'File List' could not be parsed by HTTPBuilder's default JSON parser.
     * 
     * Specifying the content type as TEXT removes the parsing from the call. Code was added to parse the returned
     * text into JSON using the more lenient 'LAX' parser.
     */
    http.request( GET, TEXT ) {
        //Since content type is text, we need to specify that a json response is acceptable. 
        headers.Accept = 'application/json'
        headers.'User-Agent' = USER_AGENT

        response.success = { respnse, reader ->

            def jsonText = reader.text
            def parser = new JsonSlurper().setType(JsonParserType.LAX)
            def jsonResp = parser.parseText(jsonText)
            //Add up the size of all the files in this directory
            //
            jsonResp.files.each {
                directorySize = directorySize + Integer.parseInt("${it.size}".toString())
            }
        }
    }

答案 2 :(得分:0)

def bufferedText = response.entity.content.getText( ParserRegistry.getCharset( response ) ).trim()
def result =  new JsonSlurper().parseText( bufferedText )

答案 3 :(得分:-2)

def 'test hello resource'(){
        when:
        def info =""
       // http.auth.basic('sysadmin', 'yax64smi')
      //  http.ignoreSSLIssues()//add for this issue Groovy:SSLPeerUnverifiedException: peer not authenticated new version (0.7.1) of HttpBuilder introduces method:ignoreSSLIssues()
        http.request( GET,JSON  ) {
            uri.path = '/hello/'
            //headers.'Authorization' = 'Basic c3lzYWRtaW46eWF4NjRzbWk='
            //headers.'Authorization' = "Basic ${"username:password".bytes.encodeBase64().toString()}"
            headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
            headers.'Content-Type' = 'application/json'
            headers.Accept = 'application/json'

            response.success = { resp ->
                def parser = new JsonSlurper().setType(JsonParserType.LAX)
                def jsonResptext = parser.parseText( resp.entity.content.getText())
                println "PUT response status: ${resp.statusLine}"
                assert resp.statusLine.statusCode == 200 ||resp.statusLine.statusCode ==201 ||resp.statusLine.statusCode ==202
                info = resp.statusLine.statusCode
               // def bufferedText = resp.entity.content.getText( ParserRegistry.getCharset( resp ) ).trim()
                println 'Headers: -----------Response data: -----'
                println "Content-Type: ${resp.headers.'Content-Type'}"
                println jsonResptext

            }
            response.failure = { resp -> println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}" }

        }

        println "Result:\n"+info
        then:
        assert info ==200 || info ==201 || info ==202

    }