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

12,350

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
Share:
12,350
DJhon
Author by

DJhon

Updated on June 04, 2022

Comments

  • DJhon
    DJhon almost 2 years

    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?