Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson deserializing into Map with an Enum Key, POJO Value

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

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:

"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.

like image 986
ecbrodie Avatar asked Nov 15 '12 21:11

ecbrodie


People also ask

How does Jackson deserialize enum?

By default, Jackson will use the Enum name to deserialize from JSON. If we want Jackson to case-insensitively deserialize from JSON by the Enum name, we need to customize the ObjectMapper to enable the ACCEPT_CASE_INSENSITIVE_ENUMS feature.

How do you serialize an enum?

1.12 Serialization of Enum Constants To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java. lang. Enum.

How do you deserialize a map?

Just like Java objects, we can serialize and deserialize Java Map by using Jackson. We can easily serialize and deserialize Map<Object, Object>, Map<Object, String>, and Map<String, String> to or from JSON-formatted strings by using Jackson.

How is enum represented in JSON?

JSON has no enum type. The two ways of modeling an enum would be: An array, as you have currently. The array values are the elements, and the element identifiers would be represented by the array indexes of the values.


2 Answers

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)
  • 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.
like image 176
StaxMan Avatar answered Oct 15 '22 04:10

StaxMan


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
public static MyEnum create(String str) {
    // code to return an enum based on the String parameter
}
like image 42
ecbrodie Avatar answered Oct 15 '22 05:10

ecbrodie