Сериализация перечислений с помощью Jackson

У меня есть Enum desrcibed ниже:

public enum OrderType { UNKNOWN(0, "Undefined"), TYPEA(1, "Type A"), TYPEB(2, "Type B"), TYPEC(3, "Type C"); private Integer id; private String name; private WorkOrderType(Integer id, String name) { this.id = id; this.name = name; } //Setters, getters.... } 

Я возвращаю массив перечислений с моим controllerом ( new OrderType[] {UNKNOWN,TYPEA,TYPEB,TYPEC}; ), а Spring сериализует его в следующую строку json:

 ["UNKNOWN", "TYPEA", "TYPEB", "TYPEC"] 

Каков наилучший подход, чтобы заставить jacksonа сериализовать enums, как POJO? Например:

 [ {"id": 1, "name": "Undefined"}, {"id": 2, "name": "Type A"}, {"id": 3, "name": "Type B"}, {"id": 4, "name": "Type C"} ] 

Я играл с разными аннотациями, но не смог добиться такого результата.

Наконец я нашел решение сам.

Мне пришлось аннотировать enum с помощью @JsonSerialize(using = OrderTypeSerializer.class) и реализовать собственный сериализатор:

 public class OrderTypeSerializer extends JsonSerializer { @Override public void serialize(OrderType value, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException { generator.writeStartObject(); generator.writeFieldName("id"); generator.writeNumber(value.getId()); generator.writeFieldName("name"); generator.writeString(value.getName()); generator.writeEndObject(); } } 
 @JsonFormat(shape= JsonFormat.Shape.OBJECT) public enum SomeEnum 

доступно с https://github.com/FasterXML/jackson-databind/issues/24

просто протестировал его с версией 2.1.2

ответ на TheZuck :

Я попробовал ваш пример, получил Json:

 {"events":[{"type":"ADMIN"}]} 

Мой код:

 @RequestMapping(value = "/getEvent") @ResponseBody public EventContainer getEvent() { EventContainer cont = new EventContainer(); cont.setEvents(Event.values()); return cont; } class EventContainer implements Serializable { private Event[] events; public Event[] getEvents() { return events; } public void setEvents(Event[] events) { this.events = events; } } 

и зависимости:

  com.fasterxml.jackson.core jackson-annotations ${jackson.version}   com.fasterxml.jackson.core jackson-core ${jackson.version}   com.fasterxml.jackson.core jackson-databind ${jackson.version}   jackson-annotations com.fasterxml.jackson.core   jackson-core com.fasterxml.jackson.core    2.1.2 

Я нашел очень красивое и сжатое решение, особенно полезное, когда вы не можете изменять classы enum, как это было в моем случае. Затем вы должны предоставить настраиваемый ObjectMapper с включенной определенной функцией. Эти функции доступны с Jackson 1.6.

 public class CustomObjectMapper extends ObjectMapper { @PostConstruct public void customConfiguration() { // Uses Enum.toString() for serialization of an Enum this.enable(WRITE_ENUMS_USING_TO_STRING); // Uses Enum.toString() for deserialization of an Enum this.enable(READ_ENUMS_USING_TO_STRING); } } 

Есть больше возможностей, связанных с перечислением, см. Здесь:

https://github.com/FasterXML/jackson-databind/wiki/Serialization-features https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features

Вот мое решение. Я хочу преобразовать enum в форму {id: ..., name: ...} .

С Jackson 1.x :

pom.xml:

  1.9.13    org.codehaus.jackson jackson-core-asl ${jackson.version}   org.codehaus.jackson jackson-mapper-asl ${jackson.version}   

Rule.java:

 import org.codehaus.jackson.map.annotate.JsonSerialize; import my.NamedEnumJsonSerializer; import my.NamedEnum; @Entity @Table(name = "RULE") public class Rule { @Column(name = "STATUS", nullable = false, updatable = true) @Enumerated(EnumType.STRING) @JsonSerialize(using = NamedEnumJsonSerializer.class) private Status status; public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public static enum Status implements NamedEnum { OPEN("open rule"), CLOSED("closed rule"), WORKING("rule in work"); private String name; Status(String name) { this.name = name; } public String getName() { return this.name; } }; } 

NamedEnum.java:

 package my; public interface NamedEnum { String name(); String getName(); } 

NamedEnumJsonSerializer.java:

 package my; import my.NamedEnum; import java.io.IOException; import java.util.*; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.SerializerProvider; public class NamedEnumJsonSerializer extends JsonSerializer { @Override public void serialize(NamedEnum value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { Map map = new HashMap<>(); map.put("id", value.name()); map.put("name", value.getName()); jgen.writeObject(map); } } 

С Jackson 2.x :

pom.xml:

  2.3.3    com.fasterxml.jackson.core jackson-core ${jackson.version}   com.fasterxml.jackson.core jackson-databind ${jackson.version}   

Rule.java:

 import com.fasterxml.jackson.annotation.JsonFormat; @Entity @Table(name = "RULE") public class Rule { @Column(name = "STATUS", nullable = false, updatable = true) @Enumerated(EnumType.STRING) private Status status; public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } @JsonFormat(shape = JsonFormat.Shape.OBJECT) public static enum Status { OPEN("open rule"), CLOSED("closed rule"), WORKING("rule in work"); private String name; Status(String name) { this.name = name; } public String getName() { return this.name; } public String getId() { return this.name(); } }; } 

Rule.Status.CLOSED переведен на {id: "CLOSED", name: "closed rule"} .

Простой способ сериализации Enum использует аннотацию @JsonFormat. @JsonFormat может настроить сериализацию Enum тремя способами.

 @JsonFormat.Shape.STRING public Enum OrderType {...} 

использует метод OrderType :: name как метод сериализации. Сериализация OrderType.TypeA является “TYPEA”

 @JsonFormat.Shape.NUMBER Public Enum OrderTYpe{...} 

в качестве метода сериализации используется OrderType :: ordinal. Сериализация типа OrderType.TypeA равна 1

 @JsonFormat.Shape.OBJECT Public Enum OrderType{...} 

обрабатывает OrderType как POJO. Сериализация OrderType.TypeA является {"id":1,"name":"Type A"}

JsonFormat.Shape.OBJECT – это то, что вам нужно в вашем случае.

Еще более сложным способом является ваше решение, указав сериализатор для Enum.

Ознакомьтесь с этой ссылкой: https://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonFormat.html.

Использовать аннотацию @JsonCreator, создать метод getType (), сериализовать с помощью toString или объекта, работающего

 {"ATIVO"} 

или

 {"type": "ATIVO", "descricao": "Ativo"} 

 import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeType; @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum SituacaoUsuario { ATIVO("Ativo"), PENDENTE_VALIDACAO("Pendente de Validação"), INATIVO("Inativo"), BLOQUEADO("Bloqueado"), /** * Usuarios cadastrados pelos clientes que não possuem acesso a aplicacao, * caso venham a se cadastrar este status deve ser alterado */ NAO_REGISTRADO("Não Registrado"); private SituacaoUsuario(String descricao) { this.descricao = descricao; } private String descricao; public String getDescricao() { return descricao; } // TODO - Adicionar metodos dinamicamente public String getType() { return this.toString(); } public String getPropertieKey() { StringBuilder sb = new StringBuilder("enum."); sb.append(this.getClass().getName()).append("."); sb.append(toString()); return sb.toString().toLowerCase(); } @JsonCreator public static SituacaoUsuario fromObject(JsonNode node) { String type = null; if (node.getNodeType().equals(JsonNodeType.STRING)) { type = node.asText(); } else { if (!node.has("type")) { throw new IllegalArgumentException(); } type = node.get("type").asText(); } return valueOf(type); } } 
  • как получить параметр в методе post spring mvc?
  • Пользовательский менеджер проверки подлинности с функцией Spring Security и Java Configuration
  • Весной MVC
  • Spring 3 MVC: один-ко-многим в динамической форме (добавление / удаление при создании / обновлении)
  • Смутно о том, как обращаться с запросами preflight CORS OPTIONS
  • Как загрузить файл с сервера с помощью jQuery AJAX и Spring MVC 3
  • INFO: Нет типов Spring WebApplicationInitializer, обнаруженных на пути к classам
  • Spring MVC @PathVariable получает усечение
  • Что рекомендуется для нереста streamов из сервлета в Tomcat
  • Бесконечная recursion с выпуском Jackson JSON и Hibernate JPA
  • Обновление статического содержимого с помощью Spring MVC и Boot
  • Давайте будем гением компьютера.