Deserialize recursive polymorphic class in GSON
deserialization, gson, java, json
Solution
To deserialize your JSON you need a custom deserializer for your Recursive interface. In that kind of class you need to examine your JSON and decide what kind of class to instantiate as the type field in the JSON itself. Here you have a basic deserializer I wrote for you example.
Of course it can be improve to manage borderline cases (for example, what happens if you do not have type field?).
package stackoverflow.questions;
import java.lang.reflect.Type;
import java.util.*;
import stackoverflow.questions.Q20254329.*;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
public class Q20327670 {
static class Complex implements Recursive {
Map<String, Recursive> map;
@Override
public String toString() {
return "Complex [map=" + map + "]";
}
}
static class Simple implements Recursive {
@Override
public String toString() {
return "Simple []";
}
}
public static class RecursiveDeserializer implements JsonDeserializer<Recursive> {
public Recursive deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Recursive r = null;
if (json == null)
r = null;
else {
JsonElement t = json.getAsJsonObject().get("type");
String type = null;
if (t != null) {
type = t.getAsString();
switch (type) {
case "complex": {
Complex c = new Complex();
JsonElement e = json.getAsJsonObject().get("map");
if (e != null) {
Type mapType = new TypeToken<Map<String, Recursive>>() {}.getType();
c.map = context.deserialize(e, mapType);
}
r = c;
break;
}
case "simple": {
r = new Simple();
break;
}
// remember to manage default..
}
}
}
return r;
}
}
public static void main(String[] args) {
String json = " { " +
" \"type\" : \"complex\", " +
" \"map\" : { " +
" \"a\" : { " +
" \"type\" : \"simple\" " +
" }, " +
" \"b\" : { " +
" \"type\" : \"complex\", " +
" \"map\" : { " +
" \"ba\" : { " +
" \"type\" : \"simple\" " +
" } " +
" } " +
" } " +
" } } ";
GsonBuilder gb = new GsonBuilder();
gb.registerTypeAdapter(Recursive.class, new RecursiveDeserializer());
Gson gson = gb.create();
Recursive r = gson.fromJson(json, Recursive.class);
System.out.println(r);
}
}
This is the result of my code:
Complex [map={a=Simple [], b=Complex [map={ba=Simple []}]}]
Problem
``` class Complex implements Recursive { Map<String, Recursive> map; ... } class Simple implements Recursive { ... } ``` How do I deserialize this json: ``` { "type" : "complex", "map" : { "a" : { "type" : "simple" }, "b" : { "type" : "complex", "map" : { "ba" : { "type" : "simple" } } } } ``` using Google GSON?