Вопрос по java – Заставить Джексона добавить дополнительную упаковку, используя аннотации

13

У меня есть следующий класс:

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"}}

Is there any JAXB / Jackson annotation I can use to achieve my goal?

В качестве обходного пути я могу обернуть свой класс другим классом:

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);

Is there any JAXB / Jackson annotation I can use to achieve my goal?

Благодарю.

Ваш Ответ

6   ответов
0

@JsonRootName(value = "message")
public class Message { ...}

затем используйте
new ObjectMapper().configure(SerializationFeature.WRAP_ROOT_VALUE, true).writeValueAs...

2

При условии, что вы не против того, чтобы у json был капиталm вmessage, то самый простой способ сделать это, чтобы аннотировать ваш класс@JsonTypeInfo.

Вы бы добавили:

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)
public class Message {
  // ...
}

получить{"Message":{"text":"Text"}}

4

Было грустно узнать, что вы должны написать собственную сериализацию для простой цели обертывания класса с помеченным объектом. Поработав над написанием собственного сериализатора, я пришел к выводу, что самое простое решение - универсальная обертка. Вот, возможно, более простая реализация приведенного выше примера:

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;
    }
}
1

С помощью Jackson 2.x можно использовать следующее, чтобы включить обертку без добавления дополнительных свойств в ObjectMapper.

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;

@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
@JsonTypeName(value = "student")
public class Student {
  private String name;
  private String id;
}
1

Если использовать пружину, то вapplication.properties файл добавить следующее: -

spring.jackson.serialization.WRAP_ROOT_VALUE=true

А потом использовать@JsonRootName аннотации к любому вашему классу, который вы хотите сериализовать. например

@JsonRootName("user")
public class User {
    private String name;
    private Integer age;
}
12

Обходной путь: вам не нужны эти геттеры / сеттеры, так что можете просто иметь:

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.

Я должен подтвердить - UNWRAP может быть достаточно; Вопрос в том, должно ли имя отображаться на карте. Но даже без@JsonRootName, существует имя по умолчанию (простое имя класса), которое может хорошо работать.
StaxMan, если имя корневого элемента строки Json необходимо игнорировать во время сериализации, требует ли Jackson 1.9 установитьDeserializationConfig.Feature.UNWRAP_ROOT_ELEMENT особенность или добавление аннотации@JsonRootName также требуется?

Похожие вопросы