简体   繁体   English

如何使用 Jackson json 注释枚举字段以进行反序列化

[英]How to annotate enum fields for deserialization using Jackson json

I am using REST web service/Apache Wink with Jackson 1.6.2.我在 Jackson 1.6.2 中使用 REST web 服务/Apache Wink。 How do I annotate an enum field so that Jackson deserializes it?如何注释枚举字段以便杰克逊反序列化它?

Inner class内部类

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

Java Bean/Request object Java Bean/请求对象

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

The Jackson docs state that it can do this via @JsonValue / @JsonCreator but provides no examples. Jackson 文档声明它可以通过@JsonValue / @JsonCreator做到这@JsonCreator但没有提供示例。

Anyone willing to spill the (java)beans, as it were?任何人都愿意把(java)beans 洒出来,就像它一样?

If you are using Jackson 1.9, serialization would be done by:如果您使用的是 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; }

so change you need is to add method to Enum type itself, so all values have it.所以你需要改变的是向 Enum 类型本身添加方法,所以所有值都有它。 Not sure if it would work on subtype.不确定它是否适用于子类型。

For @JsonCreator , having a static factory method would do it;对于@JsonCreator ,使用静态工厂方法就可以了; so adding something like:所以添加如下内容:

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

Jackson 2.0 will actually support use of just @JsonValue for both, including deserialization. Jackson 2.0 实际上将支持对两者仅使用@JsonValue ,包括反序列化。

With Jackson 2.6 or newer, the @JsonProperty annotation can be applied directly to the enum constant to change its serialization:对于Jackson 2.6或更新版本, @JsonProperty注释可以直接应用于枚举常量以更改其序列化:

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

don't annotate them, just configure your ObjectMapper instance:不要注释它们,只需配置您的 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;
}

and in your enum override the toString() method:并在您的枚举中覆盖 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;
    }
}

You don't need any annotations or custom deserializers.您不需要任何注释或自定义反序列化器。

Actually, according to the docs for JsonValue (Jackson 2.3.3):实际上,根据 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. 

So for enums, your deserialization will not work using JsonCreator because JsonValue will be used for both serialization and deserialization.因此,对于枚举,使用 JsonCreator 将无法进行反序列化,因为 JsonValue 将同时用于序列化和反序列化。 One way to do this for enums is using JsonSetter and JsonGetter.对枚举执行此操作的一种方法是使用 JsonSetter 和 JsonGetter。

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

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

Deserializer解串器

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
    }

Then, in your JavaBean...然后,在您的 JavaBean 中...

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

The following may work if the enumeration is an array or not.如果枚举是否为数组,则以下内容可能有效。 (Only for deserialization) (仅用于反序列化)

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

To consider:要考虑:

  1. The @Data annotation generates setters, getters, toString, etc. @Data 注解生成 setter、getter、toString 等。
  2. @JsonProperty("my-enums") private MyEnum[] myEnums, this is the way to annotate with jackson the field that is of type Enum ( It works if it is an array or not). @JsonProperty("my-enums") private MyEnum[] myEnums,这是用 jackson 注释 Enum 类型的字段的方法(它是否是数组都有效)。

  3. MyEnum is the enumeration of the values ​​to be mapped of the JSON object, suppose the following object: MyEnum是JSON对象要映射的值的枚举,假设如下对象:

    { "sucess": true, "my-enums": ["enum1-val", "enum3-val"] } {“成功”:真,“我的枚举”:[“enum1-val”,“enum3-val”]}

  4. The forValue function allows mapping the string values ​​of the array to Enum, it is annotated with @JsonCreator to indicate a construction factory used in deserialization. forValue 函数允许将数组的字符串值映射到 Enum,它用 @JsonCreator 注释以指示用于反序列化的构造工厂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM