Link to home
Start Free TrialLog in
Avatar of burtonrhodes
burtonrhodes

asked on

How to use Gson for mixed types?

I am trying to figure out how to parse a json string via Gson.  I have a json string (examples below) that can return mixed types into an EmailSubscriber object.  The "merges" field can have just a {string:string, string:string} pattern, OR in certain cases, one of the "strings" is actually a Grouping object.  I have included the two very simplified examples below.  

How can I tell the gson parser to handle the possibility of this extra array object?

Example parsing classes
class EmailSubscriber {
	String status;
                // How can this handle mixed types??
	HashMap<String, String> merges;
                // Getters & setters below...
}
class Grouping {
	String id;
	String name;
	String groups;
	// Getters and setters below...	
}

Open in new window


Example Json reponses
// Works
json: {"status":"subscribed","merges":{"EMAIL":"test@gmail.com","FNAME":"Burton","LNAME":"Rhodes","DROPDWN":"Eggs"}}

// Doesn't work with introduced sub array (grouping)
json: {"status":"subscribed","merges":{"EMAIL":"test@gmail.com","FNAME":"Burton","LNAME":"Rhodes","DROPDWN":"Eggs","GROUPINGS":[{"id":4809,"name":"MyGrouping","groups":"Group1, Group2"}]}}

Open in new window


Example parsing code
Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(responseBody).getAsJsonObject();
EmailSubscriber emailSubscriber = gson.fromJson(jsonObject, EmailSubscriber.class);

Open in new window


I tried changing merges to "HashMap<String, Object> merges", but json gives me a the error "com.google.gson.JsonParseException: Type information is unavailable, and the target is not a primitive: [{"id":4809,"name":"MyGrouping","groups":"Group1, Group2"}]"

I am at a loss in how to program the json parser to successfully deserialize this type of "variable" json feed.  Any suggestions?
Avatar of for_yan
for_yan
Flag of United States of America image


Well you probably will need to set up some custom derilaizer either ofr your HashMap
or for your class as a whole. Look at this example:
http://stackoverflow.com/questions/5377827/using-gson-to-parse-array-with-multiple-types
It obviously does not support HahsMaps with non-primitive types of the value objects

I guess one thing which comes to my mind is to define a wrapper class which will hold the
HashMap of your type - with strings for all fileds and I guess map for GROUPINGs
and write this custom derializer - like in that link
http://stackoverflow.com/questions/5377827/using-gson-to-parse-array-with-multiple-types 
in the second box of the answer and use that wrapper class instaed of HashMapwithin your object

Alternatiively, you can just use step-by-estep derializer - which will
check at each step if we have JSONObject or JSONArray and then take actions accordingly.
If the format of your JSON string will alwys be the same this
approach would also work, though it is less nice - but I used it for several JSON strings with
constant structure quite successfully
ASKER CERTIFIED SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of burtonrhodes
burtonrhodes

ASKER

Nice.  Sorry for the delay.  I was trying out some different methods.  Came up with something that works, but your last solution looks pretty slick.  I'll check it out!  Thanks.