복붙노트

[SPRING] Jackson과 함께 열거 형 직렬화

SPRING

Jackson과 함께 열거 형 직렬화

Enum은 아래에 설명되어 있습니다.

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

내 컨트롤러 (새로운 OrderType [] {UNKNOWN, TYPEA, TYPEB, TYPEC};)로 enum 배열을 반환하고 Spring은이를 다음 json 문자열로 직렬화합니다.

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

잭슨이 POJO처럼 enum을 직렬화하도록하는 최선의 방법은 무엇입니까? 예 :

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

다른 주석을 사용했지만 그와 같은 결과를 얻을 수 없었습니다.

해결법

  1. ==============================

    1.마침내 해결책을 찾았습니다.

    마침내 해결책을 찾았습니다.

    jumSerialize (= OrderTypeSerializer.class 사용)에 enum 주석을 달고 사용자 지정 serializer를 구현해야했습니다.

    public class OrderTypeSerializer extends JsonSerializer<OrderType> {
    
      @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();
      }
    }
    
  2. ==============================

    2.

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

    종속성은 다음과 같습니다.

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>jackson-annotations</artifactId>
          <groupId>com.fasterxml.jackson.core</groupId>
        </exclusion>
        <exclusion>
          <artifactId>jackson-core</artifactId>
          <groupId>com.fasterxml.jackson.core</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    
    <jackson.version>2.1.2</jackson.version>
    
  3. ==============================

    3.필자는 매우 훌륭하고 간결한 솔루션을 찾았습니다. 특히 제 경우와 같이 enum 클래스를 수정할 수 없을 때 유용합니다. 그런 다음 특정 기능을 사용하는 사용자 정의 ObjectMapper를 제공해야합니다. 이러한 기능은 Jackson 1.6부터 사용할 수 있습니다.

    필자는 매우 훌륭하고 간결한 솔루션을 찾았습니다. 특히 제 경우와 같이 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);
        }
    }
    

    더 많은 enum 관련 기능을 사용할 수 있습니다. 여기를 참조하십시오.

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

  4. ==============================

    4.여기 내 해결책이있다. {id : ..., name : ...} 형식으로 변환 enum을 원합니다.

    여기 내 해결책이있다. {id : ..., name : ...} 형식으로 변환 enum을 원합니다.

    Jackson 1.x 사용 :

    Pom.hml :

    <properties>
        <jackson.version>1.9.13</jackson.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>
    

    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<NamedEnum> {
        @Override
        public void serialize(NamedEnum value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            Map<String, String> map = new HashMap<>();
            map.put("id", value.name());
            map.put("name", value.getName());
            jgen.writeObject(map);
        }
    }
    

    Jackson 2.x 사용 :

    Pom.hml :

    <properties>
        <jackson.version>2.3.3</jackson.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>
    

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

    규칙. 상태 .CLOSED는 {id : "CLOSED", 이름 : "폐쇄 규칙"}으로 번역됩니다.

  5. ==============================

    5.Enum을 직렬화하는 쉬운 방법은 @JsonFormat 주석을 사용하는 것입니다. @JsonFormat은 세 가지 방법으로 열거 형의 직렬화를 구성 할 수 있습니다.

    Enum을 직렬화하는 쉬운 방법은 @JsonFormat 주석을 사용하는 것입니다. @JsonFormat은 세 가지 방법으로 열거 형의 직렬화를 구성 할 수 있습니다.

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

    serialization 메서드로 OrderType :: name을 사용합니다. OrderType.TypeA의 직렬화는 "TYPEA"입니다.

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

    serialization 메서드로 OrderType :: ordinal을 사용합니다. OrderType.TypeA의 직렬화는 1입니다.

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

    OrderType을 POJO로 취급합니다. OrderType.TypeA의 직렬화는 { "id": 1, "name": "Type A"}입니다.

    JsonFormat.Shape.OBJECT는 귀하가 필요로하는 것입니다.

    열거 형에 대한 serializer를 지정하면 솔루션이 좀 더 복잡해집니다.

    이 참고 자료를 확인하십시오. https://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonFormat.html

  6. ==============================

    6.@JsonCreator 주석을 사용하고, getType () 메소드를 작성하고, toString 또는 객체 작업과 직렬화합니다.

    @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);
        }
    
    }
    
  7. from https://stackoverflow.com/questions/7766791/serializing-enums-with-jackson by cc-by-sa and MIT license