使用 Jackson 反序列化枚举 [英] Deserializing an enum with Jackson

查看:52
本文介绍了使用 Jackson 反序列化枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying and failing to deserialize an enum with Jackson 2.5.4, and I don't quite see my case out there. My input strings are camel case, and I want to simply map to standard Enum conventions.

@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 无济于事,这是我在别处看到的一个选项.他们都炸了:

I've also tried @JsonValue on a getter to no avail, which was an option I saw reported elsewhere. They all blow up with:

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指定其序列化/反序列化值(参见此处):

Starting from Jackson 2.6, you can use @JsonProperty on each element of the enum to specify its serialization/deserialization value (see here):

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

<小时>

(这个答案的其余部分对于旧版本的 Jackson 仍然有效)


(The rest of this answer is still valid for older versions of Jackson)

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

You should use @JsonCreator to annotate a static method that receives a String argument. That's what Jackson calls a factory method:

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 有效语法,即引用值.

As the factory method expects a String, you have to use JSON valid syntax for strings, which is to have the value quoted.

这篇关于使用 Jackson 反序列化枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆