【问题标题】:How to annotate enum fields for deserialization using Jackson json如何使用 Jackson json 注释枚举字段以进行反序列化
【发布时间】:2012-03-07 04:43:02
【问题描述】:

我在 Jackson 1.6.2 中使用 REST Web 服务/Apache Wink。如何注释枚举字段以便 Jackson 反序列化它?

内部类

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

Java Bean/请求对象

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

Jackson 文档声明它可以通过 @JsonValue/@JsonCreator 执行此操作,但没有提供示例。

有谁愿意将 (java) bean 泄露出去?

【问题讨论】:

标签: java json jackson


【解决方案1】:

如果您使用的是 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】:

    使用 Jackson 2.6 或更高版本,@JsonProperty 注释可以直接应用于枚举常量以更改其序列化:

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

    【讨论】:

    • 这个已经停产了,不知道具体的版本。
    • @SimrandeepSingh:我正在使用 Jackson 2.9.9(通过 Spring Boot 2.1.6),它工作得很好。
    • @SimrandeepSingh 根据@JsonProperty Javadocs,这仍然可用,并且自 Jackson 2.6 以来一直可用。
    【解决方案3】:

    不要注释它们,只需配置您的 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;
        }
    }
    

    您不需要任何注释或自定义反序列化程序。

    【讨论】:

    • 我需要在哪里配置对象映射器?你能帮忙吗
    • toString 方法对我来说是关键。没有更多的改变,所以伙计们,看看你的 toString 方法!
    • 如果您希望同一个映射器中的不同类有不同的行为怎么办?
    【解决方案4】:

    实际上,根据 JsonValue (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. 
    

    因此,对于枚举,您的反序列化将无法使用 JsonCreator 进行,因为 JsonValue 将用于序列化和反序列化。 对枚举执行此操作的一种方法是使用 JsonSetter 和 JsonGetter。

    【讨论】:

      【解决方案5】:
      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;
      

      【讨论】:

        【解决方案6】:

        如果枚举是否为数组,以下可能会起作用。 (仅用于反序列化)

        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 注解生成 setter、getter、toString 等。
        2. @JsonProperty("my-enums") private MyEnum[] myEnums,这是用 jackson 注释 Enum 类型字段的方法( 不管它是不是一个数组都有效)。

        3. MyEnum是JSON对象要映射的值的枚举,假设如下对象:

          { “成功”:是的, “我的枚举”:[“enum1-val”,“enum3-val”] }

        4. forValue函数允许将数组的字符串值映射到Enum,用@JsonCreator注解表示反序列化使用的构造工厂。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-31
          • 1970-01-01
          • 2015-10-19
          • 1970-01-01
          • 2020-07-17
          • 1970-01-01
          相关资源
          最近更新 更多