反序列化枚举场与杰克逊

问题描述 投票:1回答:2

我有一个简单枚举Days

public enum Days {
    @JsonProperty("Monday")
    MONDAY("Monday"),
    @JsonProperty("Tuesday")
    TUESDAY("Tuesday");

    private String day;

    Days(String day) {
        this.day = day;
    }

    @JsonValue
    public String getDay() {
        return day;
    }
}

和一类Event

public class Event {
    private Days day;
    private String name;


    @JsonCreator
    public Event(@JsonProperty("day") Days day,
             @JsonProperty("name") String name) {
    this.day = day;
    this.name = name;
}

    public Days getDay() {
        return day;
    }

    public String getName() {
        return name;
    }
}

我用杰克逊2.9,this answer表明,采用@JsonProperty应该是够了,但是我很难反序列化这样的:

public static void main(String[] args) throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    Event event = new Event(Days.MONDAY, "Birthday");

    String serialisedEvent = objectMapper.writeValueAsString(event);
    System.out.println(serialisedEvent);
    // {"day":"Monday","name":"Birthday"}

    Event deserialisedEvent = objectMapper.convertValue(serialisedEvent, Event.class);
    // Exception in thread "main" java.lang.IllegalArgumentException: Cannot construct instance of `xyz.blabla.Event` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"day":"Monday","name":"Birthday"}')
    // at [Source: UNKNOWN; line: -1, column: -1]
    // at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3750)
    System.out.println(deserialisedEvent.getDay());
}

我在春天启动2项目中使用Java 11和杰克逊2.9。我怎样才能使这项工作?

java jackson objectmapper
2个回答
4
投票

杰克逊反序列化方法被调用readValue

convertValue的目的是不同的 - 其序列的对象(其可以是一个字符串 - 这将成为一个JSON-字串文本然后)第一,然后将结果反序列化到目标类型的一个对象。

下面应该工作:

Event deserialisedEvent = objectMapper.readValue(serialisedEvent, Event.class);

0
投票

您没有默认的构造函数,但一个参数的构造函数。

你有@JsonCreator进行注解,以便杰克逊用它来反序列化JSON的:

@JsonCreator 
public Event(Days day, String name) {
    this.day = day;
    this.name = name;
}

序列化Java对象到JSON,构造函数没有被杰克逊,因为它没有创建Java实例,但只使用getter检索它的性能。所以,它的工作。但是,反序列化JSON到Java对象,杰克逊需要实例化目标类。默认情况下,它会寻找无参数的构造函数。

还要注意的是注释与@JsonProperty("...")构造函数的参数,如果你使用ParameterNamesModule如不需要:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new ParameterNamesModule());

春季启动2提供为你,你要看杰克逊。 在这里,你需要它,因为你不使用由Spring启动映射器接线,但你自己实例化。

除了不需要设在枚举的@JsonProperty注解之一:

public enum Days {
    @JsonProperty("Monday")
    MONDAY("Monday"),
    @JsonProperty("Tuesday")
    TUESDAY("Tuesday");
    //...
}

它允许改变枚举的串行输出,但实际上你并不需要去改变它,你把它映射到当前用于枚举杰克逊映射day字段值...

© www.soinside.com 2019 - 2024. All rights reserved.