For serializer: I do not see any reason (except see at the bottom at my answer) why you should need any custom serializer. Gson serializes fluently almost anything.
The problem comes with deserialization because your List<A> aList
- after serialized to JSON object - does not contain information in its objects that what was the implementing class. I am afraid that the only available option is by peeking what are the fields (or any similar spying, values perhaps) in the JSON objects you are currently serializing.
For example, you could have deserialiser like:
public class PeekingDeserializer implements JsonDeserializer<A> {
private final Gson gson = new Gson();
@Override
public A deserialize(JsonElement je, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
return buildInstance(je);
}
private A buildInstance(JsonElement je) {
Class<? extends A> classA;
if (null != je.getAsJsonObject().getAsJsonPrimitive("aInt")) {
classA = Aa.class;
} else if (null != je.getAsJsonObject().getAsJsonPrimitive("bInt")) {
classA = Bb.class;
} else {
throw new IllegalArgumentException("Could not resolve class");
}
return gson.fromJson(je, classA);
}
}
And as you see above implementation trusts that fields aInt
, bInt
always exist. They can be null
I think but they must exist in JSON object. The main thing is that there must be something that you can use to recognize the type of object. If you cannot recognize the type, if you cannot code the deserializer it cannot be expected that Gson could do it in some automagical way.
I think that Michał Ziober in his comment was thinking either using RuntimeTypeAdapterFactory or possibility to add the type information when serializing C
(or List<A>
). For the latter you could have use of custome serializer - using it to stamp the type information as field type
- but if your JSON comes elsewhere and not serialized by you this option does not help.