我使用JAVA 1.6和Jackson 1.9.9,我有一个enum

public enum Event {
    FORGOT_PASSWORD("forgot password");

    private final String value;

    private Event(final String description) {
        this.value = description;
    }

    @JsonValue
    final String value() {
        return this.value;
    }
}

我已经添加了一个@JsonValue,这似乎做的工作,它序列化对象:

{"event":"forgot password"}

但当我尝试反序列化时,我得到

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.globalrelay.gas.appsjson.authportal.Event from String value 'forgot password': value not one of declared Enum instance names

我错过了什么?


当前回答

您可以自定义任何属性的反序列化。

使用将要处理的属性的annotationJsonDeserialize (import com.fasterxml.jackson.databin .annotation. jsondeserialize)声明反序列化类。如果这是一个Enum:

@JsonDeserialize(using = MyEnumDeserialize.class)
private MyEnum myEnum;

通过这种方式,您的类将被用于反序列化属性。这是一个完整的例子:

public class MyEnumDeserialize extends JsonDeserializer<MyEnum> {

    @Override
    public MyEnum deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        MyEnum type = null;
        try{
            if(node.get("attr") != null){
                type = MyEnum.get(Long.parseLong(node.get("attr").asText()));
                if (type != null) {
                    return type;
                }
            }
        }catch(Exception e){
            type = null;
        }
        return type;
    }
}

其他回答

我是这样做的:

// Your JSON
{"event":"forgot password"}

// Your class to map 
public class LoggingDto {
    @JsonProperty(value = "event")
    private FooEnum logType;
}

//Your enum
public enum FooEnum {

    DATA_LOG ("Dummy 1"),
    DATA2_LOG ("Dummy 2"),
    DATA3_LOG ("forgot password"),
    DATA4_LOG ("Dummy 4"),
    DATA5_LOG ("Dummy 5"),
    UNKNOWN ("");

    private String fullName;

    FooEnum(String fullName) {
        this.fullName = fullName;
    }

    public String getFullName() {
        return fullName;
    }

    @JsonCreator
    public static FooEnum getLogTypeFromFullName(String fullName) {
        for (FooEnum logType : FooEnum.values()) {
            if (logType.fullName.equals(fullName)) {
                return logType;
            }
        }
        return UNKNOWN;
    }


}

因此,类LoggingDto的属性“logType”的值将是DATA3_LOG

注意,在2015年6月的这次提交(Jackson 2.6.2及以上版本)中,你现在可以简单地写:

public enum Event {
    @JsonProperty("forgot password")
    FORGOT_PASSWORD;
}

行为记录在这里:https://fasterxml.github.io/jackson-annotations/javadoc/2.11/com/fasterxml/jackson/annotation/JsonProperty.html

从Jackson 2.6开始,这个注释也可以用来改变Enum的序列化,如下所示: public enum MyEnum { @JsonProperty THE_FIRST_VALUE(“theFirstValue”), another_value @JsonProperty(“another_value”); } 作为使用JsonValue注释的替代方法。

在枚举上下文中,现在(从2.0开始)使用@JsonValue可用于序列化和反序列化。

根据@JsonValue的jackson-annotations javadoc:

注意:当用于Java枚举时,一个额外的特性是带注释的方法返回的值也被认为是要反序列化的值,而不仅仅是要序列化的JSON字符串。这是可能的,因为Enum值的集合是常量,可以定义映射,但不能在一般POJO类型;因此,这并不用于POJO反序列化。

因此,在jackson 2.0+中,像上面那样对Event枚举进行注释(对于序列化和反序列化都适用)。

我发现了一个非常好的和简洁的解决方案,特别是当您不能修改枚举类时,就像在我的例子中一样。然后,您应该提供一个启用了特定特性的自定义ObjectMapper。这些特性从Jackson 1.6开始就可以使用了。所以你只需要在你的enum中写入toString()方法。

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

还有更多与枚举相关的特性可用,请参见这里:

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

以我为例,这就是解决方案:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum PeriodEnum {

    DAILY(1),
    WEEKLY(2),
    ;

    private final int id;

    PeriodEnum(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return this.name();
    }

    @JsonCreator
    public static PeriodEnum fromJson(@JsonProperty("name") String name) {
        return valueOf(name);
    }
}

序列化和反序列化以下json:

{
  "id": 2,
  "name": "WEEKLY"
}

我希望这能有所帮助!