java - 使用 Jackson 反序列化枚举

我正在尝试使用 Jackson 2.5.4 反序列化枚举,但未能成功,我不太了解我的情况。我的输入字符串是驼峰式大小写,我想简单地映射到标准 Enum 约定。

@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum Status {
    READY("ready"),
    NOT_READY("notReady"),
    NOT_READY_AT_ALL("notReadyAtAll");

    private static Map<String, Status> FORMAT_MAP = Stream
            .of(Status.values())
            .collect(toMap(s -> s.formatted, Function.<Status>identity()));

    private final String formatted;

    Status(String formatted) {
        this.formatted = formatted;
    }

    @JsonCreator
    public Status fromString(String string) {
        Status status = FORMAT_MAP.get(string);
        if (status == null) {
            throw new IllegalArgumentException(string + " has no corresponding value");
        }
        return status;
    }
}

我还在 getter 上尝试了 @JsonValue 无济于事,这是我在其他地方看到的一个选项。他们都爆发了:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of ...Status from String value 'ready': value not one of declared Enum instance names: ...

我做错了什么?

最佳答案

编辑:从 Jackson 2.6 开始,您可以在枚举的每个元素上使用 @JsonProperty 来指定其序列化/反序列化值( see here ):

public enum Status {
    @JsonProperty("ready")
    READY,
    @JsonProperty("notReady")
    NOT_READY,
    @JsonProperty("notReadyAtAll")
    NOT_READY_AT_ALL;
}

(此答案的其余部分仍然适用于 jackson 的旧版本)

您应该使用 @JsonCreator 来注释接收 String 参数的静态方法。这就是 jackson 所说的工厂方法:

public enum Status {
    READY("ready"),
    NOT_READY("notReady"),
    NOT_READY_AT_ALL("notReadyAtAll");

    private static Map<String, Status> FORMAT_MAP = Stream
        .of(Status.values())
        .collect(Collectors.toMap(s -> s.formatted, Function.identity()));

    private final String formatted;

    Status(String formatted) {
        this.formatted = formatted;
    }

    @JsonCreator // This is the factory method and must be static
    public static Status fromString(String string) {
        return Optional
            .ofNullable(FORMAT_MAP.get(string))
            .orElseThrow(() -> new IllegalArgumentException(string));
    }
}

这是测试:

ObjectMapper mapper = new ObjectMapper();

Status s1 = mapper.readValue("\"ready\"", Status.class);
Status s2 = mapper.readValue("\"notReadyAtAll\"", Status.class);

System.out.println(s1); // READY
System.out.println(s2); // NOT_READY_AT_ALL

由于工厂方法需要一个 String,因此您必须对字符串使用 JSON 有效语法,即引用值。

https://stackoverflow.com/questions/31689107/

相关文章:

java - 如何使用 @ResponseBody 从 Spring Controller 返回 J

json - PostgreSQL 中 JSON 数据类型的大小限制

javascript - 在输入隐藏字段中存储返回 json 值

json - 使用 JSON 协议(protocol)处理版本控制的最佳方法是什么?

ruby-on-rails - 设计 API 身份验证

java - 在 JSON 对象中解析 JSON 数组

c# - 在 C# 中解析 Json 字符串

javascript - 如何 JSON 字符串化 javascript 日期并保留时区

c# - 将枚举序列化为字符串

php - PHP中的序列化或json?