2014-09-06 62 views
0

我是一名Groovy新手,並嘗試從Groovy腳本連接到GitHub API,但是當HTTPBuilder嘗試解析JSON響應時出現奇怪的錯誤。Groovy 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

+3

保存響應JSON和嘗試解析它Groovy的JSON解析器 – injecteer 2014-09-06 21:47:59

+0

請你提供JSON響應你越來越了? – Opal 2014-09-07 12:32:07

+0

提供的代碼對我來說工作正常。 – Opal 2014-09-07 12:36:58

回答

1

這裏是我的代碼工作周圍

/* 
    * 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()) 
      } 
     } 
    } 
+0

你應該更新你的現有答案,而不是創建第二個答案。 – 3urdoch 2014-09-14 15:54:12

+0

@murdoch我正面臨同樣的問題,但不幸的是改變Groovy版本目前不是一種選擇。任何關於如何將您的解決方法適用於將JSON發佈到遠程服務的方案的想法,或者我註定只要'Content-Type = applicaton/json?' – Sitati 2015-06-17 08:58:20

+0

我實際上發現此解決方法 - https:/ /gist.github.com/zedar/abbb3c01635c0d6a977f 僅在JsonSlurper之前調用只讀取讀取器的響應處理程序閉包。 – Sitati 2015-06-17 10:34:33

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

    } 
+0

請不要發佈代碼的答案。解釋代碼是如何工作的。 – 2016-04-18 03:37:11

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