source

잭슨 json을 사용하여 역직렬화를 위해 열거형 필드에 주석을 다는 방법

manysource 2023. 2. 16. 22:07

잭슨 json을 사용하여 역직렬화를 위해 열거형 필드에 주석을 다는 방법

잭슨 1.6.2와 함께 REST 웹 서비스/Apache Wink를 사용하고 있습니다.잭슨이 열거 필드를 역직렬화하려면 어떻게 주석을 달아야 합니까?

내부 클래스

public enum BooleanField
{
    BOOLEAN_TRUE        { public String value() { return "1";} },
    BOOLEAN_FALSE       { public String value() { return "0";} },

Java Bean/Request 객체

BooleanField locked;
public BooleanField getLocked() {return locked;}

Jackson 문서에는 이 작업은 다음 방법으로 수행할 수 있다고 기술되어 있습니다.@JsonValue/@JsonCreator는 예를 제시하지 않습니다.

누구 실토할 사람?

Jackson 1.9 를 사용하고 있는 경우는, 다음의 조작에 의해서 시리얼화가 실행됩니다.

public enum BooleanField {
   BOOLEAN_TRUE("1")
   ;

   // either add @JsonValue here (if you don't need getter)
   private final String value;

   private BooleanField(String value) { this.value = value; }

   // or here
   @JsonValue public String value() { return value; }

따라서 필요한 변경은 Enum 유형 자체에 메서드를 추가하여 모든 값에 해당 메서드를 포함시키는 것입니다.서브타입으로 동작할지는 잘 모르겠습니다.

위해서@JsonCreator공장 출하 시 스태틱메서드를 사용하면 됩니다.따라서 다음과 같은 것을 추가합니다.

@JsonCreator
public static BooleanField forValue(String v) { ... }

Jackson 2.0은 실제로 다음과 같은 기능을 지원합니다.@JsonValue두 가지 모두에 대해 설명하겠습니다.

잭슨 2.6 이후에서는 주석을 열거 상수에 직접 적용하여 직렬화를 변경할 수 있습니다.

public enum BooleanField
{
    @JsonProperty("1")
    BOOLEAN_TRUE,
    @JsonProperty("0")
    BOOLEAN_FALSE
}

주석을 달지 말고 ObjectMapper 인스턴스를 구성하기만 하면 됩니다.

private ObjectMapper createObjectMapper() {
    final ObjectMapper mapper = new ObjectMapper();
    // enable toString method of enums to return the value to be mapped
    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
    return mapper;
}

열거형에서는 toString() 메서드를 덮어씁니다.

public enum SectionType {
START("start"),
MORE("more");

    // the value which is used for matching
    // the json node value with this enum
    private final String value;

    SectionType(final String type) {
        value = type;
    }

    @Override
    public String toString() {
        return value;
    }
}

주석이나 사용자 지정 역직렬자는 필요하지 않습니다.

실제로 Json Value 문서(Jackson 2.3.3)에 따르면 다음과 같습니다.

NOTE: when use for Java enums, one additional feature is
 * that value returned by annotated method is also considered to be the
 * value to deserialize from, not just JSON String to serialize as.
 * This is possible since set of Enum values is constant and it is possible
 * to define mapping, but can not be done in general for POJO types; as such,
 * this is not used for POJO deserialization. 

따라서 Enum의 경우 JsonValue가 직렬화와 직렬화 해제 모두에 사용되므로 JsonCreator를 사용하면 직렬화 해제 기능이 작동하지 않습니다.Enums의 경우 JsonSetter와 JsonGetter를 사용하는 방법이 있습니다.

public enum BooleanField
{
    BOOLEAN_TRUE("1"),      
    BOOLEAN_FALSE("0");
    
    private final String value;

    BooleanField( int value ) { this.value = value; }
    
}

디세리어라이저

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class BooleanFieldDeserializer extends Json Deserializer<BooleanField> {
    
    public BooleanField deserialize( JsonParser p, DeserializationContext ctx )
    throws IOException 
    {
        // boilerplate code for every deserializer
        ObjectCodec objectCodec = p.getCodec();
        JsonNode node = objectCodec.readTree(p);

        // customizable part for your impl
        String booleanFieldString = node.asText();
        return valueOf( booleanFieldString ); <- Enum-supplied method
    }

그러면 JavaBean에서...

@JsonDeserialize(using = BooleanFieldDeserializer.class)
BooleanField locked;

열거가 배열인지 아닌지는 다음 작업을 수행할 수 있습니다. (직렬화 해제 시에만 해당).

package com.stack.model;

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import lombok.Data;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonPropertyOrder({ "success", "my-enums" })
public class MyObjectJSON {

    @JsonProperty("sucess")
    private boolean success;

    @JsonProperty("my-enums")
    private MyEnum[] myEnums;


    static enum MyEnum {
        Enum1, Enum2, Enum3, Enum4, EnumN;

        private static Map<String, MyEnum> myEnumsMap = new HashMap<String, MyEnum>(5);

        static {
            myEnumsMap.put("enum1-val", Enum1);
            myEnumsMap.put("enum2-val", Enum2);
            myEnumsMap.put("enum3-val", Enum3);
            myEnumsMap.put("enum4-val", Enum4);
            myEnumsMap.put("enumn-val", EnumN);
        }

        @JsonCreator
        public static MyEnum forValue(String value) {
            return myEnumsMap.get(value.toLowerCase());
        }
    }
}

고려해야 할 사항:

  1. @Data 주석에서는 setters, getters, toString 등이 생성됩니다.
  2. @JsonProperty("my-enums") private MyEnums [] myEnums, 이것은 Enum 타입의 필드에 잭슨을 사용하여 주석을 붙이는 방법입니다(배열 여부에 관계없이 동작합니다).

  3. MyEnum은 JSON 오브젝트의 매핑되는 값의 열거입니다.다음 오브젝트를 상정합니다.

    { "success": true, "my-enums": ["enum1-val", "enum3-val"] }

  4. forValue 함수를 사용하면 배열의 문자열 값을 Enum에 매핑할 수 있습니다.이 함수는 @JsonCreator에 주석을 달아 역직렬화에 사용되는 건설 팩토리를 나타냅니다.

언급URL : https://stackoverflow.com/questions/9300191/how-to-annotate-enum-fields-for-deserialization-using-jackson-json