Force Jackson добавить дополнительную упаковку с помощью аннотаций
У меня есть следующий класс:
public class Message {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
При преобразовании экземпляра в JSON с использованием Jackson по умолчанию я получаю:
{"text":"Text"}
Я хотел бы получить:
{"message":{"text":"Text"}}
Есть ли какая-либо аннотация JAXB/Jackson, которую я могу использовать для достижения своей цели?
В качестве обходного пути я могу скомпоновать свой класс другим классом:
public class MessageWrapper {
private Message message;
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
}
или более общее решение:
public class JsonObjectWrapper<T> {
/**
* Using a real map to allow wrapping multiple objects
*/
private Map<String, T> wrappedObjects = new HashMap<String, T>();
public JsonObjectWrapper() {
}
public JsonObjectWrapper(String name, T wrappedObject) {
this.wrappedObjects.put(name, wrappedObject);
}
@JsonAnyGetter
public Map<String, T> any() {
return wrappedObjects;
}
@JsonAnySetter
public void set(String name, T value) {
wrappedObjects.put(name, value);
}
}
Что можно использовать так:
Message message = new Message();
message.setText("Text");
JsonObjectWrapper<Message> wrapper = new JsonObjectWrapper<Message>("message", message);
Есть ли какая-либо аннотация JAXB/Jackson, которую я могу использовать для достижения своей цели?
Спасибо.
Ответы
Ответ 1
В обходном пути: вам не нужны эти геттеры/сеттеры, поэтому просто:
public class MessageWrapper {
public Message message;
}
или, возможно, добавить конструктор удобства:
public class MessageWrapper {
public Message message;
@JsonCreator
public MessageWrapper(@JsonProperty("message") Message m) {
message = m;
}
}
Существует также способ добавления обертки; с 1.9 вы можете использовать SerializationConfig.Feature.WRAP_ROOT_ELEMENT
и DeserializationConfig.Feature.UNWRAP_ROOT_ELEMENT
. И если вы хотите изменить имя обертки (по умолчанию это просто неквалифицированное имя класса), вы можете использовать @JsonRootName
аннотацию
Jackson 2.0 добавляет дополнительные динамические параметры через ObjectReader
и ObjectWriter
, а также аннотации JAX-RS.
Ответ 2
Было грустно узнать, что вы должны написать специальную сериализацию для простой цели обертывания класса с помеченным объектом. После того, как я начал писать собственный сериализатор, я пришел к выводу, что самым простым решением является общая оболочка. Здесь возможно более простая реализация вашего примера выше:
public final class JsonObjectWrapper {
private JsonObjectWrapper() {}
public static <E> Map<String, E> withLabel(String label, E wrappedObject) {
HashMap<String, E> map = new HashMap<String, E>();
map.put(label, wrappedObject);
return map;
}
}
Ответ 3
Если вы не возражаете против json с капиталом m
в message
, то самый простой способ сделать это - аннотировать ваш класс @JsonTypeInfo
.
Вы бы добавили:
@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)`
public class Message {
// ...
}
чтобы получить {"Message":{"text":"Text"}}
Ответ 4
Упрощенный/лучший способ сделать это:
@JsonRootName(value = "message")
public class Message { ...}
затем используйте
new ObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true).writeValueAs...
Ответ 5
Если вы используете spring, то в файле application.properties
добавьте следующее: -
spring.jackson.serialization.WRAP_ROOT_VALUE = истина
И затем используйте аннотацию @JsonRootName
для любого из ваших классов, которые вы хотите сериализовать. например.
@JsonRootName("user")
public class User {
private String name;
private Integer age;
}