[android]为什么我得到 JsonSyntaxException︰ 预期 BEGIN_ARRAY 但这里是字符串?

发布时间: 2017/3/19 14:44:29
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我有一个 JSON 文件︰

{
"settings": {
    "header": {
        "id": "240A64CDC43F",
        "filename": "network",
        "sequence": "0",
        "last_modified": "2015-04-21T16:33",
        "JSON_file_version": "2.1"
    },
    "data": {
        "engine_config": {
            "bed_name": "IdealTempCDC43F",
            "provisioned": "false",
            "connected": "false",
            "IP_address": "192.168.10.1",
            "connection_error": "None"
        },
        "networks": {
            "available": "7",
            "SSIDs": {
                "wireless_1": {
                    "SSID": "$$ASI_WIFI$$",
                    "mac_address": "A0:EC:F9:11:35:04",
                    "channel": "11",
                    "RSSI": "-64dBm",
                    "security": "true",
                    "security_type": "WPA"
                },
                "wireless_2": {
                    "SSID": "$$ASI_GUEST$$",
                    "mac_address": "A0:EC:F9:11:35:02",
                    "channel": "11",
                    "RSSI": "-65dBm",
                    "security": "true",
                    "security_type": "WPA"
                }
            }
        }
    }
}
}

解析此 json 我用这个︰

HttpResponse response = client.execute(request); 
String strResponse = response.toString();
parseJSON(strResponse);

public void parseJSON(String jsonString) {
  Gson gsonParser = new Gson();
  ProveQuerySetting gsonResponse = new ProveQuerySetting();
  Type collectionType = new TypeToken<Collection<ProveQuerySetting>>() {
  }.getType();
  gsonResponse = gsonParser.fromJson(jsonString, collectionType);
  String str = gsonParser.toJson(gsonResponse);
  System.out.println(" final json " + str);
}

但我正在此异常︰

04-21 07:08:13.864: W/System.err(4187): com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $
04-21 07:08:13.864: W/System.err(4187): com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $
04-21 07:08:13.865: W/System.err(4187):     at com.google.gson.Gson.fromJson(Gson.java:822)
04-21 07:08:13.865: W/System.err(4187):     at com.google.gson.Gson.fromJson(Gson.java:775)
04-21 07:08:13.865: W/System.err(4187):     at com.google.gson.Gson.fromJson(Gson.java:724)
04-21 07:08:13.865: W/System.err(4187):     at com.easi.main.network.NetworkCom.parseJSON(NetworkCom.java:127)
04-21 07:08:13.865: W/System.err(4187):     at com.easi.main.network.NetworkCom.sendFirst(NetworkCom.java:50)
04-21 07:08:13.865: W/System.err(4187):     at com.easi.main.setting.ConnectToBox$MyAsyncTask.doInBackground(ConnectToBox.java:89)
04-21 07:08:13.865: W/System.err(4187):     at com.easi.main.setting.ConnectToBox$MyAsyncTask.doInBackground(ConnectToBox.java:1)
04-21 07:08:13.865: W/System.err(4187):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
04-21 07:08:13.865: W/System.err(4187):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
04-21 07:08:13.865: W/System.err(4187):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
04-21 07:08:13.865: W/System.err(4187):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
04-21 07:08:13.865: W/System.err(4187):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
04-21 07:08:13.865: W/System.err(4187):     at java.lang.Thread.run(Thread.java:818)
04-21 07:08:13.865: W/System.err(4187): Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $
04-21 07:08:13.865: W/System.err(4187):     at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
04-21 07:08:13.866: W/System.err(4187):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:79)
04-21 07:08:13.866: W/System.err(4187):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
04-21 07:08:13.866: W/System.err(4187):     at com.google.gson.Gson.fromJson(Gson.java:810)
04-21 07:08:13.866: W/System.err(4187):     ... 12 more

这里是我的 POJO 类︰

public class ProveQuerySetting {
  ProvQueryData provEngnData;
  ProvQueryHeader provEngnhHeader;

  public ProvQueryData getProvEngnData() {
    return provEngnData;
  }

  public void setProvEngnData(ProvQueryData provEngnData) {
    this.provEngnData = provEngnData;
  }

  public ProvQueryHeader getProvEngnhHeader() {
    return provEngnhHeader;
  }

  public void setProvEngnhHeader(ProvQueryHeader provEngnhHeader) {
    this.provEngnhHeader = provEngnhHeader;
  }
}

为什么我得到这异常?

解决方法 1:

好吧,你正在使用默认的 Gson。太好了 !Gson 默认是智能,但没那么智能。你必须设计您的类到的格式完全匹配的 json 你正在背,或使用 @SerializedName annotation ,如果你不想要设计自定义的反序列化程序。当说完全匹配,我的意思是,字段名称必须完全相同作为序列化 Gson,无论是在字段名称或 annotation

我创建了以下的 Pojo (包括你的与已修改的字段名称)。我并不包括 getter/setter 方法简洁︰

public class ProvEngineConfig {
  private String bed_name;
  private String provisioned;
  private String connected;
  private String IP_Address;
  private String connection_error;
}

public class ProvNetworks {
  private String available;
  private Map<String, ProvSSID> SSIDs;  // Notice this is a map
}

public class ProveQuerySetting {
  ProvQueryData data;
  ProvQueryHeader header;
}

public class ProvQueryData {
  ProvEngineConfig engine_config;
  ProvNetworks networks;
}

public class ProvQueryHeader {
  String id;
  String filename;
  String sequence;
  String last_modified;
  String JSON_file_version;
}

public class ProvSSID {
  String SSID;
  String mac_address;
  String channel;
  String RSSI;
  String security;
  String security_type;
}

同样,您看到的字段名称到底是如何在你的 JSON 一样吗?请注意,在 ProvNetworks ,我用一张地图,因为你提供的 JSON 是无线对的名称完全匹配的 SSID 对象地图。

一旦我的 Pojo 建立类似于下面,还请注意,您提供的 JSON 不 Collection 查询的 settings ,它实际上是 Map<String, ProvQuerySetting> ,你从这个词映射 "settings" 到引擎 config 对象。所以像这样进行︰

public static void parseJSON(String jsonString) {
  Gson gsonParser = new Gson();
  Map<String, ProveQuerySetting> gsonResponse; // You don't need to do new here
  Type collectionType = new TypeToken<Map<String, ProveQuerySetting>>() {}.getType();
  gsonResponse = gsonParser.fromJson(jsonString, collectionType);

  String str = gsonParser.toJson(gsonResponse);
  System.out.println(" final json " + str);
}

输出︰

final json {"settings":{"data":{"engine_config":{"bed_name":"IdealTempCDC43F","provisioned":"false","connected":"false","connection_error":"None"},"networks":{"available":"7","SSIDs":{"wireless_1":{"SSID":"$$ASI_WIFI$$","mac_address":"A0:EC:F9:11:35:04","channel":"11","RSSI":"-64dBm","security":"true","security_type":"WPA"},"wireless_2":{"SSID":"$$ASI_GUEST$$","mac_address":"A0:EC:F9:11:35:02","channel":"11","RSSI":"-65dBm","security":"true","security_type":"WPA"}}}},"header":{"id":"240A64CDC43F","filename":"network","sequence":"0","last_modified":"2015-04-21T16:33","JSON_file_version":"2.1"}}}

总结︰

你要么需要︰

  1. 你的 Pojo 和字段名称/注释字段名称相匹配的 JSON完全匹配
  2. 编写您自己的自定义序列,如中所述JsonReader
赞助商