2

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?

6
  • jsonlint.com - not a valid json Commented Apr 22, 2015 at 9:35
  • This is valid json.Working for iOS Commented Apr 22, 2015 at 9:36
  • I take you JSON you posted, and valiidadted with jsonlint.com . JSON Is not correct in Parse error on line 1: { settings: { -----^ Expecting 'STRING', '}' Commented Apr 22, 2015 at 9:38
  • 1
    @BlueGreen jsonformatter.curiousconcept.com - 2 sites independetly are saying it's not valid json. iOS may have error handling that can work with it, but it's not valid json Commented Apr 22, 2015 at 9:39
  • @BlueGreen do you get the same error with this edited json? Commented Apr 22, 2015 at 9:53

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

4 Comments

"I mean, the field names must be exactly the same as the serialized Gson." Not necessarily, you can use the annotation @SerializedName if you want to stick with the java coding conventions. For example: @SerializedName("json_name") private datatype javaName;
No Doubt... Your suggestion helped a lot. I really appreciate you effort.
I need one more small help, How to get data from "collectionType". A small hint will be sufficient.
@durron597..Now data get parsed successfully. How i will used parsed data for view in my project
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.