2010-10-17 23 views
7

Je suis en train de JSON désérialiser une MyRootClass de classe avec une propriété qui est une collection d'éléments d'une deuxième classe MyClass:Jackson: sérialisation collection personnalisée à JSON

public class MyRootClass { 
    private List<MyInterface> list = new ArrayList<MyInterface>(); 
    // getter/setter 
} 

public class MyClass implements MyInterface { 
    private String value = "test";  
    // getter/setter 
} 

Le code suivant:

MyRootClass root = new MyRootClass(); 
root.getList().add(new MyClass()); 
ObjectMapper mapper = new ObjectMapper(); 
mapper.writeValue(System.out, root); 

cette sortie Génère JSON:

{"list": [ {"value":"test"} ] } 

au lieu de ce que je dois, chaque objet dans le col lection sérialisé avec un nom:

{"list": [ {"myclass": {"value":"test"}} ] } 

Existe-t-il un moyen d'y parvenir en utilisant Jackson? J'ai pensé écrire un sérialiseur personnalisé, mais je n'ai rien trouvé en rapport avec une collection d'objets.

Répondre

7

Cela dépend de ce que vous voulez exactement obtenir avec le nom; mais oui, cela peut être fait si vous voulez inclure 'myclass' ici est de type information (ou peut agir comme si elle était utilisée, si vous n'utilisez pas Jackson pour désérialiser cela n'a pas vraiment d'importance).

Si oui, vous annoter MyInterface:

@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) 

et MyClass avec:

@JsonTypeName("myclass") 

(si vous ne définissez pas, le nom par défaut serait nom non qualifié de la classe)

@JsonTypeInfo ci-dessus définit que le nom de type doit être utilisé (au lieu du nom de classe Java, ou de la méthode personnalisée), et l'inclusion est faite en utilisant un objet wrapper (les alternatives sont wrapper array et as-property)

Vous devriez alors voir la sortie attendue.

1

Ce que vous voulez, c'est d'inclure le nom de la classe dans la sortie. Ce n'est pas ainsi que se comportent les sérialiseurs json - ils incluent uniquement les noms de champs.

Ce que vous pouvez faire est d'introduire une autre classe.

class MyClass implements MyInterface { 
    private MyOtherClass myclass; 
} 

class MyOtherClass { 
    private String value = "test"; 
} 
+0

Merci. C'est ce que j'essayais d'éviter, parce que j'utilise un modèle de classe hérité (je ne peux pas le modifier), mais j'ai besoin d'obtenir ce format JSON (également une restriction imposée par un système tiers). –

+1

vous pouvez envelopper le modèle de classe hérité à des fins de sérialisation. – Bozho

1

Vous pouvez utiliser un objet d'aide comme celui-ci:

public static class MyObject { 
    public int i; 
    public MyObject(int i) { this.i = i; } 
    public MyObject() {} 
} 

@JsonDeserialize(contentAs=MyObject.class) 
public static class MyHelperClass extends ArrayList<MyObject> { 

} 

@Test 
public void testCollection() throws JsonGenerationException, JsonMappingException, IOException { 
    final Collection<MyObject> l = new ArrayList<MyObject>(); 
    l.add(new MyObject(1)); 
    l.add(new MyObject(2)); 
    l.add(new MyObject(3)); 

    final ObjectMapper mapper = new ObjectMapper(); 

    final String s = mapper.writeValueAsString(l); 
    final Collection<MyObject> back = mapper.readValue(s, MyHelperClass.class); 

}