Why am I getting a JsonSyntaxException: Expected BEGIN_ARRAY but was STRING here?

允我心安 提交于 2019-12-12 04:48:57

问题


I have one JSON file:

{
"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"
                }
            }
        }
    }
}
}

For parsing this json I am using this:

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

and

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);
}

But I am getting this exception:

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

Here is my POJO class:

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;
  }
}

Why I am getting this exception?


回答1:


Okay, so you are trying to use the default Gson. Great! The default Gson is smart, but not that smart. You have to design your classes to exactly match the format of the json you're getting back, or use the @SerializedName annotation, if you don't want to design a custom deserializer. When I say exactly match, I mean, the field names must be exactly the same as the serialized Gson, either in the field name or the annotation.

I created the following POJOs (including yours, with modified field names). I have not included the getters/setters for brevity:

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;
}

Again, do you see how the field names are exactly the same as the ones in your JSON? Notice that in ProvNetworks, I'm using a map, because the JSON you provided is a map of wireless names to exactly matching SSID objects.

Once my POJOs were set up like the following, notice also that your provided JSON is not a Collection of Query settings, it's actually a Map<String, ProvQuerySetting>, you map from the word "settings" to the Engine config object. So I parsed it like this:

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);
}

Output:

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"}}}

To summarize:

You either need to:

  1. Exactly match your POJOs and field names/annotated field names to match the JSON
  2. Write your own custom deserializer, as described in JsonReader



回答2:


Gson API is good but i found one more API Jackson more robust and user friendly. Need two jar files jackson-core-asl-1.8.5 and jackson-mapper-asl-1.8.5 and then

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();
    }

And last but not least be care full about your POJO classes.

1.Field name should be same.

2.If getting Unrecognized exception at some field then use Annotation like this

  @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;
    }

}

Above all fields, where the possibility to throw exception.



来源:https://stackoverflow.com/questions/29793314/why-am-i-getting-a-jsonsyntaxexception-expected-begin-array-but-was-string-here

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!