Java 使用 Jackson 反序列化枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31689107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:26:06  来源:igfitidea点击:

Deserializing an enum with Hymanson

javajsonHymanson

提问by jwilner

I'm trying and failing to deserialize an enum with Hymanson 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.

我正在尝试使用 Hymanson 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;
    }
}

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

我也试过@JsonValue一个吸气剂但无济于事,这是我在别处看到的一个选项。他们都炸了:

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

What am I doing wrong?

我究竟做错了什么?

采纳答案by Federico Peralta Schaffner

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

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

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


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

(这个答案的其余部分仍然适用于旧版本的Hyman逊)

You should use @JsonCreatorto annotate a static method that receives a Stringargument. That's what Hymanson calls a factory method:

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

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

This is the test:

这是测试:

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

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

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

回答by Konstantin Kulagin

This is probably a faster way to do it:

这可能是一种更快的方法:

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

 private final String formatted;

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

 @Override
 public String toString() {
   return formatted;
 }
}

public static void main(String[] args) throws IOException {
  ObjectMapper mapper = new ObjectMapper();
  ObjectReader reader = mapper.reader(Status.class);
  Status status = reader.with(DeserializationFeature.READ_ENUMS_USING_TO_STRING).readValue("\"notReady\"");
  System.out.println(status.name());  // NOT_READY
}

回答by Stefan

The solutions on this page work only for single field and @JsonFormat(shape = JsonFormat.Shape.NATURAL) (default format)

此页面上的解决方案仅适用于单个字段和 @JsonFormat(shape = JsonFormat.Shape.NATURAL)(默认格式)

this works for multiple fields and @JsonFormat(shape = JsonFormat.Shape.OBJECT)

这适用于多个字段和 @JsonFormat(shape = JsonFormat.Shape.OBJECT)

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum PinOperationMode {
    INPUT("Input", "I"),
    OUTPUT("Output", "O")
    ;

    private final String mode;
    private final String code;

    PinOperationMode(String mode, String code) {
        this.mode = mode;
        this.code = code;
    }

    public String getMode() {
        return mode;
    }

    public String getCode() {
        return code;
    }

    @JsonCreator
    static PinOperationMode findValue(@JsonProperty("mode") String mode, @JsonProperty("code") String code) {
        return Arrays.stream(PinOperationMode.values()).filter(pt -> pt.mode.equals(mode) && pt.code.equals(code)).findFirst().get();
    }
}

回答by Sileria

For whoever is searching for enums with integer json properties. Here is what worked for me:

对于正在搜索具有整数 json 属性的枚举的人。这是对我有用的:

enum class Status (private val code: Int) {
    PAST(0),
    LIVE(2),
    UPCOMING(1);
    companion object {
        private val codes = Status.values().associateBy(Status::code)
        @JvmStatic @JsonCreator fun from (value: Int) = codes[value]
    }
}

回答by Arun Kumar

@JsonCreator
public static Status forValue(String name)
{
    return EnumUtil.getEnumByNameIgnoreCase(Status.class, name);
}

Adding this static method would resolve your problem of deserializing

添加此静态方法将解决您的反序列化问题

回答by alhamwa

You could use @JsonCreatorannotation to resolve your problem. Take a look at https://www.baeldung.com/Hymanson-serialize-enums, there's clear enough explanation about enum and serialize-deserialize with Hymanson lib.

您可以使用@JsonCreator注释来解决您的问题。看看https://www.baeldung.com/Hymanson-serialize-enums,关于 enum 和 serialize-deserialize with Hymanson lib 有足够清楚的解释。