java Jackson 使用枚举键、POJO 值反序列化为 Map

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13406568/
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-10-31 12:36:40  来源:igfitidea点击:

Hymanson deserializing into Map with an Enum Key, POJO Value

javajsonserializationHymansonjsonserializer

提问by ecbrodie

I am trying to deserialize JSON into a Java POJO using Hymanson. Without giving away confidential information, here is an example stack trace when ObjectMapper's deserialization fails:

我正在尝试使用 Hymanson 将 JSON 反序列化为 Java POJO。在不泄露机密信息的情况下,以下是 ObjectMapper 的反序列化失败时的示例堆栈跟踪:

org.codehaus.Hymanson.map.JsonMappingException: Can not construct Map key of type com.example.MyEnum from String "coins": not a valid representation: Can not construct Map key of type com.example.MyEnum from String "coins": not one of values for Enum class

My JSON looks like this:

我的 JSON 如下所示:

"foo": {
    "coins": null,
    ...
}

And the class I want to deserialize into has this field:

我想反序列化的类有这个字段:

private Map<MyEnum, MyPojo> foo;

And my enum type looks like this:

我的枚举类型如下所示:

public enum MyEnum {
    COINS("coins"),
    ...
}

I do realize that I am trying to deserialize a null value. But I believe this should still work: the result of the deserialization should be equivalent to having a Map with foo.put(MyEnum.COINS, null), which is indeed a valid Java instruction. Help is much appreciated, thanks in advance.

我确实意识到我正在尝试反序列化一个空值。但我相信这应该仍然有效:反序列化的结果应该相当于有一个 Map with foo.put(MyEnum.COINS, null),这确实是一个有效的 Java 指令。非常感谢帮助,提前致谢。

回答by StaxMan

In addition to one good solution presented (factory method), there are 2 other ways:

除了提出的一种好的解决方案(工厂方法)之外,还有另外两种方法:

  • If 'MyEnum.toString()' would return "coins", you can make Hymanson use "toString()" over "name()"with ObjectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
  • You could add some other method to return id to use, and mark that method with @JsonValueannotation (you can actually use that on toString()as well, instead of enabling above feature) -- if that annotation exists, value returned by that method is used as the id.
  • 如果“MyEnum.toString()”会返回“硬币”,你可以让Hyman逊使用“toString()”而不是“name()” ObjectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
  • 您可以添加一些其他方法来返回要使用的 id,并用@JsonValue注释标记该方法(您实际上也可以使用它toString(),而不是启用上述功能)——如果该注释存在,则该方法返回的值用作ID。

回答by ecbrodie

GRR! Figured it out.

太棒了!弄清楚了。

Solution for me was to create a static method, annotated with @JsonCreator, in my enum that creates an instance of the enum, based on a String parameter. It looked like this:

对我来说,解决方案是@JsonCreator在我的枚举中创建一个用 , 注释的静态方法,该方法基于 String 参数创建枚举的实例。它看起来像这样:

@JsonCreator
public static MyEnum create(String str) {
    // code to return an enum based on the String parameter
}

回答by hoaz

Provide a static factory method in your enumeration class that constructs enum by string and annotate it with @JsonCreator:

在您的枚举类中提供一个静态工厂方法,该方法通过字符串构造枚举并使用@JsonCreator 对其进行注释:

@JsonCreator
public static MyEnum fromValue(String v) {
    for (MyEnum myEnum : values()) {
        if (myEnum.text.equals(v)) {
            return myEnum;
        }
    }
    throw new IllegalArgumentException("invalid string value passed: " + v);
}