【问题标题】:Why am I getting a JsonSyntaxException: Expected BEGIN_ARRAY but was STRING here?为什么我收到 JsonSyntaxException: Expected BEGIN_ARRAY but was STRING here?
【发布时间】:2015-04-22 09:32:11
【问题描述】:

我有一个 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;
  }
}

为什么我会收到此异常?

【问题讨论】:

  • jsonlint.com - 不是一个有效的 json
  • 这是有效的 json.Working for iOS
  • 我带你使用你发布的 JSON,并用 jsonlint.com 验证。 Parse error on line 1: { settings: { -----^ Expecting 'STRING', '}'中的 JSON 不正确
  • @BlueGreen jsonformatter.curiousconcept.com - 2 个站点独立说它不是有效的 json。 iOS 可能有可以使用的错误处理,但它不是有效的 json
  • @BlueGreen 这个编辑过的 json 会出现同样的错误吗?

标签: java android json exception gson


【解决方案1】:

好的,所以您正在尝试使用默认的 Gson。伟大的!默认的 Gson 是聪明的,但不是那么聪明。您必须将您的类设计为完全匹配您返回的 json 格式,或者如果您不想设计自定义反序列化器,请使用 @SerializedName 注释。当我说完全匹配时,我的意思是,字段名称必须与序列化的 Gson 完全相同,无论是在字段名称还是注释中。

我创建了以下 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,它实际上是 Map&lt;String, ProvQuerySetting&gt;,您从单词 "settings" 映射到引擎配置对象。所以我是这样解析的:

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 中所述

【讨论】:

  • “我的意思是,字段名称必须和序列化的Gson完全一样。” 不一定,如果你想坚持的话可以使用注解@SerializedName Java 编码约定。例如:@SerializedName("json_name") private datatype javaName;
  • 毫无疑问...您的建议很有帮助。我真的很感谢你的努力。
  • 我还需要一个小帮助,如何从“collectionType”获取数据。一个小提示就足够了。
  • @durron597..现在数据解析成功。我将如何在我的项目中使用解析的数据进行查看
【解决方案2】:

Gson API 很好,但我发现还有一个 API Jackson 更健壮且用户友好。需要两个jar文件jackson-core-asl-1.8.5和jackson-mapper-asl-1.8.5 然后

ObjectMapper mapper = new ObjectMapper();
    MAinpojo object = null;
    System.out.println("json string  "+jsonString.trim());
    try {
         object = mapper.readValue(new URL("http://192.168.xx.x/pmmm-zzzz"), MAinpojo.class);
    } catch (JsonParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JsonMappingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

最后但并非最不重要的是要全神贯注于您的 POJO 课程。

1.字段名称应相同。

2.如果在某些领域得到无法识别的异常,那么使用这样的注释

  @JsonIgnoreProperties(ignoreUnknown=true)
public class MAinpojo {

     @JsonProperty("settings") 
     ProveQuerySetting settings;


     @JsonProperty("settings") 
     public ProveQuerySetting getSettings() {
        return settings;
    }

    public void setSettings(ProveQuerySetting settings) {
        this.settings = settings;
    }

}

首先是所有字段,哪里有可能抛出异常。

【讨论】:

    猜你喜欢
    • 2021-12-17
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多