Jsonreader 解析错误

Posted

技术标签:

【中文标题】Jsonreader 解析错误【英文标题】:Jsonreader parse error 【发布时间】:2016-11-15 19:04:22 【问题描述】:

我有以下代码:

reader = new JsonReader(new InputStreamReader(con.getInputStream()));

它返回以下 JSON:


  "results": [
    
      "bioguide_id": "D000626",
      "in_office": true,
      "thomas_id": "02296",
      "govtrack_id": "412675",
      "crp_id": "N00038767",
      "fec_ids": [
        "H6OH08315"
      ],
      "first_name": "Warren",
      "nickname": null,
      "last_name": "Davidson",
      "middle_name": null,
      "name_suffix": null,
      "gender": "M",
      "birthday": "1970-03-01",
      "leadership_role": null,
      "term_start": "2016-06-09",
      "term_end": "2017-01-03",
      "state": "OH",
      "state_name": "Ohio",
      "party": "R",
      "title": "Rep",
      "chamber": "house",
      "phone": "202-225-6205",
      "fax": null,
      "website": null,
      "office": "1011 Longworth House Office Building",
      "contact_form": null,
      "votesmart_id": 166760,
      "district": 8,
      "oc_email": null,
      "ocd_id": "ocd-division/country:us/state:oh/cd:8"
    ,
    
      "bioguide_id": "L000585",
      "in_office": true,
      "thomas_id": "02295",
      "govtrack_id": "412674",
      "crp_id": "N00037031",
      "fec_ids": [
        "H6IL18088"
      ],
      "first_name": "Darin",
      "nickname": null,
      "last_name": "LaHood",
      "middle_name": null,
      "name_suffix": null,
      "gender": "M",
      "birthday": "1968-07-05",
      "leadership_role": null,
      "term_start": "2015-09-17",
      "term_end": "2017-01-03",
      "state": "IL",
      "state_name": "Illinois",
      "party": "R",
      "title": "Rep",
      "chamber": "house",
      "phone": "202-225-6201",
      "fax": null,
      "website": "https://lahood.house.gov/",
      "office": "2464 Rayburn House Office Building",
      "contact_form": "https://lahood.house.gov/contact/email",
      "votesmart_id": 128760,
      "district": 18,
      "oc_email": "Rep.Lahood@opencongress.org",
      "twitter_id": "RepLaHood",
      "youtube_id": null,
      "facebook_id": "1499570210366431",
      "ocd_id": "ocd-division/country:us/state:il/cd:18"
    
  ],
  "count": 538,
  "page": 
    "count": 2,
    "per_page": 2,
    "page": 1
  

我通过以下方式解析阅读器:

try 

    reader.beginObject();
    while (reader.hasNext()) 
        String name = reader.nextName();
        if (name.equals("results"))
            reader.beginArray();
            while (reader.hasNext()) 
                reader.beginObject();
                while (reader.hasNext()) 
                    String id = reader.nextName();
                    if(id.equals("birthday"))
                        Log.d("id", id);
                    else
                        reader.skipValue();
                
            
        

        else 
            reader.skipValue();
        
    


catch (IOException e)
    Log.w("Error",e.getMessage());

我收到以下错误:

E/androidRuntime: FATAL EXCEPTION: main
                  Process: com.app.congress.congressapp, PID: 5095
java.lang.IllegalStateException: Expected a name but was STRING
   at android.util.JsonReader.nextName(JsonReader.java:390)
   at com.app.congress.congressapp.GetAllStates.onPostExecute(ByState.java:57)
   at com.app.congress.congressapp.GetAllStates.onPostExecute(ByState.java:30)
   at android.os.AsyncTask.finish(AsyncTask.java:636)
   at android.os.AsyncTask.access$500(AsyncTask.java:177)
   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:135)
   at android.app.ActivityThread.main(ActivityThread.java:5254)
   at java.lang.reflect.Method.invoke(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime: Error reporting crash
android.os.DeadObjectException
   at android.os.BinderProxy.transactNative(Native Method)
   at android.os.BinderProxy.transact(Binder.java:496)
   at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:4164)
   at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:89)
   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)

有没有办法以不同的方式解析 Jsonreader?我想要生日、end_term、bioguide_id 等字段的值。像这样手动解析它很困难,我必须进行许多其他可能返回不同 Json 结果的 API 调用,然后我又不得不花时间解析它。我尝试使用 BufferedReader,但如果返回大型 Json 文件,则会出现 Out Of Memory 错误。

【问题讨论】:

How to parse JSON in Android的可能重复 我认为它不是重复的,因为我不能使用 BufferedReader,因为它为大型 Json 回报提供了 OutOfMemory。 这不是重要的部分。你得到一个字符串,把它放入new JSONObject,然后开始解析 我觉得我必须编辑这一行...reader = new JsonReader(new InputStreamReader(con.getInputStream()));...你能告诉我如何因为我之前使用过BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream()));它给了我内存不足的问题 如果要继续使用InputStream,需要相应地调用endObject()endArray() 【参考方案1】:

仔细查看您的代码:

                        String id = reader.nextName();
                        if(id.equals("birthday"))
                            Log.d("id", id);
                        else
                            reader.skipValue();

当“生日”是属性名称时,您不使用该值,因此在下一次循环中,您调用nextName(),但解析器仍在该值上。

改用这个:

                        String id = reader.nextName();
                        if(id.equals("birthday")) 
                            Log.d("id", id);
                            reader.nextString(); // or reader.skipValue()
                         else 
                            reader.skipValue();
                        

正如 cmets 所指出的,您需要为每个 beginObject() 匹配一个 endObject(),并为每个 beginArray() 匹配一个 endArray()

【讨论】:

谢谢...帖子被标记为重复...我怎样才能将其删除?? 代码 a/ 无法编译,而 b/ 如果它 didi 会产生令人惊讶的结果。 @Anirban 重复在评论中被建议,但 Q 没有这样标记,所以不用担心。 :)【参考方案2】:

我假设您正在使用AsyncTask 进行网络调用。这很乏味,您可以通过这种方式做很多非常糟糕的事情(https://www.youtube.com/watch?v=jtlRNNhane0)。使用 OkHttp(由 HttpUrlConnection 在后台使用)、Retrofit、Volley、Picasso 等库要好得多。它不仅降低了复杂性,而且在某些情况下比 AsyncTasks 快得多(@ 987654322@).

使用 Retrofit 之类的库意味着您可以使用 FactoryConverter 自动将 JSON 转换为您的 POJO(无需手动阅读)。您需要做的就是创建一个 POJO 来匹配您的 JSON(http://www.jsonschema2pojo.org/) 并定义 API 接口和回调,然后 Retrofit 会处理剩下的事情。

要将 Retrofit 与 Gson 转换器一起使用,请将以下依赖项添加到您的 gradle 构建文件中:

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

这是一个使用 Gson 转换器转换为 POJO 的 Service 类的简单示例:

首先创建一个接口类来定义您的 API 调用:

public interface GitHubService 
  @GET("users/user/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);

然后使用(由 Retrofit 负责实现)创建它的实例:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

GitHubService service = retrofit.create(GitHubService.class);

然后你拨打电话:

Call<List<Repo>> repos = service.listRepos("octocat");

您将获得已从 JSON 转换的定义的 POJO。

查看以下资源以更好地掌握它:

https://square.github.io/retrofit/

https://github.com/square/retrofit/

IMO 最佳改造文档:https://futurestud.io/tutorials/retrofit-getting-started-and-android-client

【讨论】:

很好,但这并不能回答问题。 "像这样手动解析它很困难,我必须进行许多其他 API 调用,这些调用可能会返回不同的 Json 结果,然后我不得不再次花时间解析它。我尝试使用 BufferedReader 但这给出了一个大型 Json 文件返回时出现内存不足错误。”我正在回答这个..

以上是关于Jsonreader 解析错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 JsonReader 类 Android 解析 Json

使用 JsonReader 解析时 JsonArray 或 JsonObject 为空

Gson全解析之一:JsonReader的beginObject()

Gson全解析之二:JsonReader的其它方法

如何使用 JsonReader 跳过不需要的值?

GitHub Actions 因从 JsonReader 错误读取 JToken 而失败