简体   繁体   English

杰克逊用Enum Key,POJO值反序列化到Map中

[英]Jackson deserializing into Map with an Enum Key, POJO Value

I am trying to deserialize JSON into a Java POJO using Jackson. 我试图使用Jackson将JSON反序列化为Java POJO。 Without giving away confidential information, here is an example stack trace when ObjectMapper's deserialization fails: 在不泄露机密信息的情况下,这是ObjectMapper反序列化失败时的示例堆栈跟踪:

org.codehaus.jackson.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. 我确实意识到我正在尝试反序列化null值。 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. 但我相信这仍然有效:反序列化的结果应该等同于使用带有foo.put(MyEnum.COINS, null)的Map,这确实是一个有效的Java指令。 Help is much appreciated, thanks in advance. 非常感谢帮助,在此先感谢。

In addition to one good solution presented (factory method), there are 2 other ways: 除了提出的一个好的解决方案(工厂方法)之外,还有另外两种方法:

  • If 'MyEnum.toString()' would return "coins", you can make Jackson use "toString()" over "name()"with ObjectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING) 如果'MyEnum.toString()'会返回“硬币”,你可以让Jackson使用“toString()”而不是“name()”使用ObjectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
  • You could add some other method to return id to use, and mark that method with @JsonValue annotation (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. 您可以添加一些其他方法来返回要使用的id,并使用@JsonValue注释标记该方法(您实际上也可以在toString()上使用它,而不是启用上面的功能) - 如果该注释存在,则返回该值方法用作id。

GRR! 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. 我的解决方案是在我的枚举中创建一个静态方法,用@JsonCreator注释,根据String参数创建枚举实例。 It looked like this: 它看起来像这样:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM