Complex nested Data types won't deserialize to intended classes using a standard approach.
As of now, I have this working code, which deserializes json to Map<String, ? extends T>
structure:
private static <T> Map<String, ? extends T> deserializeTypeAdaptableJson(Class<T> baseType, List<Class<? extends T>> subclasses, String json) {
PolymorphicJsonAdapterFactory<T> factory = PolymorphicJsonAdapterFactory.of(baseType, "type");
for (Class<? extends T> subclass : subclasses) {
factory = factory.withSubtype(subclass, subclass.getSimpleName());
}
Moshi moshi = new Moshi.Builder().add(factory).build();
ParameterizedType type = Types.newParameterizedType(Map.class, String.class, baseType);
JsonAdapter<Map<String, ? extends T>> adapter = moshi.adapter(type);
return adapter.fromJson(json);
What I actually need to deserialize is Map<String, List<? extends T>>
, but this code
private static <T> Map<String, List<? extends T>> deserializeTypeAdaptableJson(Class<T> baseType, List<Class<? extends T>> subclasses, String json) {
PolymorphicJsonAdapterFactory<T> factory = PolymorphicJsonAdapterFactory.of(baseType, "type");
for (Class<? extends T> subclass : subclasses) {
factory = factory.withSubtype(subclass, subclass.getSimpleName());
}
Moshi moshi = new Moshi.Builder().add(factory).build();
ParameterizedType type = Types.newParameterizedType(Map.class, String.class, List.class, baseType);
JsonAdapter<Map<String, List<? extends T>>> adapter = moshi.adapter(type);
return adapter.fromJson(json);
however gives me the correct structure - Map
with String
keys and List
values, but inside of those lists instead of subclasses' instances, I receive Gson's LinkedHashTreeMap
with "type" property storing the actual class.
I couldn't find an example for deserializing nested collections. What do I need to add?
CodePudding user response:
It seems that to deserialize nested collections we have to pass nested parametrized types to the adapter. After changing this
ParameterizedType type = Types.newParameterizedType(Map.class, String.class, List.class, baseType);
ParameterizedType type = Types.newParameterizedType(Map.class, String.class, Types.newParameterizedType(List.class, baseType));
I now have a working solution - I get a Map
with List<? extends T>
values, where values are actual descendants of a common ancestor and not LinkedHashTreeMap
s.