如何使用 Jackson json 注释枚举字段以进行反序列化
Posted
技术标签:
【中文标题】如何使用 Jackson json 注释枚举字段以进行反序列化【英文标题】:How to annotate enum fields for deserialization using 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 泄露出去?
【问题讨论】:
类似:Jackson enum Serializing and DeSerializer 【参考方案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());
考虑:
-
@Data 注解生成 setter、getter、toString 等。
@JsonProperty("my-enums") private MyEnum[] myEnums,这是用 jackson 注释 Enum 类型字段的方法( 不管它是不是一个数组都有效)。
MyEnum是JSON对象要映射的值的枚举,假设如下对象:
“成功”:是的, “我的枚举”:[“enum1-val”,“enum3-val”]
forValue函数允许将数组的字符串值映射到Enum,用@JsonCreator注解表示反序列化使用的构造工厂。
【讨论】:
以上是关于如何使用 Jackson json 注释枚举字段以进行反序列化的主要内容,如果未能解决你的问题,请参考以下文章
将 Jersey/Jackson 配置为不使用 @XmlElement 字段注释进行 JSON 字段命名
如何在没有jackson注释的情况下忽略反序列化的某些字段?