Джексон: пользовательская коллекция сериализации к JSON
Вопрос
Я пытаюсь JSON-Serialize класс MyRootclass с недвижимостью, которая представляет собой коллекцию элементов второго класса MyClass:
public class MyRootClass {
private List<MyInterface> list = new ArrayList<MyInterface>();
// getter / setter
}
public class MyClass implements MyInterface {
private String value = "test";
// getter / setter
}
Следующий код:
MyRootClass root = new MyRootClass();
root.getList().add(new MyClass());
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(System.out, root);
Создает этот вывод JSON:
{"list": [ {"value":"test"} ] }
Вместо того, что мне нужно, каждый объект в коллекции сериализован с именем:
{"list": [ {"myclass": {"value":"test"}} ] }
Есть ли способ достичь его, используя Джексон? Я думал о написании пользовательского сериализатора, но я не нашел ничего, связанного с коллекцией объектов.
Решение
Это зависит от того, что именно вы хотите достичь с именем; Но да, это можно сделать, если вы хотите включить здесь «MyClass», - это информация, это информация (или может действовать как если бы она была использована; если вы не используете Jackson для десериализации, это не имеет значения).
Если это так, вы бы аннотировали MyInterface:
@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
и MyClass с:
@JsonTypeName("myclass")
(Если вы не определите это, имя по умолчанию было бы неквалифицированное название класса)
@JsonTypeInfo
Выше определяет, что имя типа должно использоваться (вместо имени класса Java, или пользовательский метод), и включение осуществляется с помощью объекта обертки (альтернативы являются массив обертки и As-свойство)
Таким образом, вы должны увидеть ожидаемый вывод.
Другие советы
То, что вы хотите, это включить имя класса на выходе. Это не то, как ведут себя как json serializers - они включают только имена полевых полей.
Что вы можете сделать, это представить еще один класс.
class MyClass implements MyInterface {
private MyOtherClass myclass;
}
class MyOtherClass {
private String value = "test";
}
Вы можете использовать вспомогательный объект, как это:
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);
}