Jsonreader解析错误

Jsonreader parse error

我有以下代码:

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

它 return 如下 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
  }
}

我按以下方式解析 reader:

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.access0(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 等字段的值。像这样手动解析它很困难,我必须进行许多其他 API 调用,这些调用可能 return 不同Json 结果又一次我不得不花时间解析它。我尝试使用 BufferedReader,但在大 Json 文件 return.

的情况下会出现内存不足错误

仔细看你的代码:

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

当 "birthday" 是 属性 名称时,您不会使用该值,因此在下一次循环中,您调用 nextName() 但解析器仍在运行值。

改用这个:

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

另外,正如评论指出的那样,您需要为每个 beginObject() 匹配一个 endObject(),为每个 beginArray() 匹配一个匹配的 endArray()

我假设您正在使用 AsyncTask 进行网络呼叫。这很乏味,你可以做很多非常糟糕的事情(https://www.youtube.com/watch?v=jtlRNNhane0) this way. You are much, much better of using libraries like OkHttp(Used by HttpUrlConnection under the hood), Retrofit, Volley, Picasso, etc. It not only reduces complexity but also is much faster than AsyncTasks in some situations(http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/)。

使用像 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'

下面是一个服务 class 使用 Gson 转换器转换为 POJO 的简单示例:

首先创建一个接口 class 来定义您的 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");

你得到一个你定义的 POJO 已经从 JSON.

转换而来

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

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

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

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