2017-01-25 3 views
1

Ich brauche Hilfe, hier ist die Beschreibung der Aufgabe:
1. Ich habe Basis SchnittstelleDeserialize JSON mit Jackson mit komplexer polymorpher Struktur

interface IPolymorphicModel 

2. Ich habe einige verschachtelten Schnittstellen:

interface IContentItem extends IPolymorphicModel 
interface IAttachment extends IPolymorphicModel 

3. ich habe einige Implementierungen:

public class MediaAttachment implements IAttachment 

public class Article implements IContentItem { 
private List<IAttachment> attachements; 
} 

I usi bin ng jackson (auch ich probierte Gson mit registerTypeAdapterFactory), um aktuelle JSON-Struktur zu analysieren. Ich verwende nächsten Ansatz für Deserialisierung json mit einzelnen Deserializer für alle verschachtelten Objekte:

Module module = new SimpleModule() 
module.setDeserializerModifier(new BeanDeserializerModifier() { 
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, 
           BeanDescription beanDesc, 
           JsonDeserializer<?> deserializer){ 
if (IPolymorphicModel.class.isAssignableFrom(beanDesc.getBeanClass())){ 
    return new PolymorphicJsonDeserializer() 
} 
return super.modifyDeserializer(config, beanDesc, deserializer); 
}) 

Aber es ist das Problem mit inneren Elemente-Analyse: wie Sie inneres Objekt sehen kann Objekt mit den gleichen super enthalten, und wenn jackson versuchen, sie zu analysieren es weiß nichts über IPolymorphicModel und die Registrierung derselben BeanDeserializerModifier ist nicht möglich, weil es Stapelüberlauf verursachen wird.

Antwort

0

Ich fand die Lösung. Und es ist zumindest in diesem Fall ziemlich einfach. Um solche Aufgaben zu lösen, müssen Sie jackson TypeIdResolver verwenden. Hier ein Beispiel:

1. Zuerst müssen Sie Ihre Basisklasse mit Anmerkungen versehen, wo modelType Ihr Feld, mit dem Sie identifizieren können, die genau Kind der Basisklasse Sie verwenden:

@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, 
     include = JsonTypeInfo.As.PROPERTY, 
     property = "modelType") 
@JsonTypeIdResolver(IdResolver.class) 
interface IPolymorphic 

2. Implementieren Sie Ihre IdResolver.class eigen:

public class IdResolver implements TypeIdResolver { 

    private JavaType baseType = null; 

    @Override 
    public void init(JavaType baseType) { 
     this.baseType = baseType; 
    } 

    @Override 
    public String idFromValue(Object value) { 
     return idFromValueAndType(value, value.getClass()); 
    } 

    @Override 
    public String idFromValueAndType(Object value, Class<?> suggestedType) { 
     String id = ""; 
     for (Map.Entry<String, Class<? extends IPolymorphic>> entry : PolymorphicTypeRegistry.Companion.getInstance().getMap().entrySet()) { 
      if (entry.getValue() == suggestedType) return entry.getKey(); 
     }   
     return id; 
    } 

    @Override 
    public String idFromBaseType() { 
     return idFromValueAndType(null, baseType.getRawClass()); 
    } 

    @Override 
    public JavaType typeFromId(String id) { 
     Class clazz = PolymorphicTypeRegistry.Companion.getInstance().get(id); 
     JavaType javaType = TypeFactory.defaultInstance().constructSpecializedType(baseType, clazz); 
     return javaType; 
    } 

    @Override 
    public JavaType typeFromId(DatabindContext context, String id) { 
     return typeFromId(id); 
    } 

    @Override 
    public String getDescForKnownTypeIds() { 
     return ""; 
    } 

    @Override 
    public JsonTypeInfo.Id getMechanism() { 
     return JsonTypeInfo.Id.CUSTOM; 
    } 
} 
  1. In zwei vorherigen Schritten, die wir konfigurieren jackson das gleiche deserialize Verhalten für alle verschachtelten Klassen von IPolymorphic, so dem letzten Schritt zu nennen - wir brauchen t o registrieren Deserializer für IPolymorphic:

    public void configureJackson() { 
        ObjectMapper objectMapper = new ObjectMapper(); 
        Module module = new SimpleModule(); 
        module.addDeserializer(IPolymorphic.class, new PolymorphicJsonDeserializer()); 
        objectMapper.registerModule(module); 
    } 
    
Verwandte Themen