12

我正在尝试使用 Jackson 将 JSON 反序列化为 Java POJO。在不泄露机密信息的情况下,以下是 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

我的 JSON 看起来像这样:

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

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

private Map<MyEnum, MyPojo> foo;

我的枚举类型如下所示:

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

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

4

3 回答 3

10

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

  • 如果 'MyEnum.toString()' 会返回 "coins",你可以让 Jackson 使用 "toString()" 而不是 "name()" withObjectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
  • 您可以添加一些其他方法来返回要使用的 id,并使用@JsonValue注释标记该方法(您实际上也可以使用它toString(),而不是启用上述功能)——如果存在该注释,则该方法返回的值用作ID。
于 2012-11-16T00:53:19.663 回答
9

GRR!弄清楚了。

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

@JsonCreator
public static MyEnum create(String str) {
    // code to return an enum based on the String parameter
}
于 2012-11-15T22:06:57.910 回答
6

在您的枚举类中提供一个静态工厂方法,该方法通过字符串构造枚举并使用@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);
}
于 2012-11-15T22:11:40.893 回答