stix
stix

Reputation: 1146

How can I deserialize a list of enums using Jackson JSON?

I'm working on a configuration system. I'd like to be able to load config values from a JSON file and have them "automagically" convert to the Java type I need. I'm using Jackson for the JSON parsing. For primitive types like floats and strings, it's no big deal, but I'm running into a snag with enums.

Let's say I have the following enum:

public enum SystemMode
{
    @JsonProperty("Mode1")
    MODE1("Mode1"),
    @JsonProperty("Mode2")
    MODE2("Mode2"),
    @JsonProperty("Mode3")
    MODE3("Mode3");

    private final String name;

    private SystemMode(String name)
    {
        this.name = name;
    }

    @Override
    @JsonValue
    public String toString()
    {
        return this.name;
    }    
}

Now, let's say I want to represent a list of values of this enum for a given config variable using the following JSON representation:

{ 
    "Project" : "TEST",
    "System" : {
        "ValidModes" : ["Mode1", "Mode2"]
      }
}

And I'd like to be able to do something like the following:

ArrayList<SystemMode> validModes = (ArrayList<SystemMode>) configurator.getConfigValue("/System/ValidModes");

For reference, my configurator class's getConfigValue method is essentially a thin wrapper over the Jackson JSON parsing:

public Object getConfigValue(String JSON_String)
{
    JsonNode node = JsonNodeFactory.instance.objectNode().at(JSON_String);
    return objectMapper.convertValue(node, Object.class);
}

(The real method has some exception checking that has been omitted for clarity).

Now, when I call the above, Jackson correctly deduces that I want an ArrayList and fills it. However, instead of getting an ArrayList of SystemMode enums, I get an ArrayList of Strings and immediately throw an exception when I attempt to use the list. I have tried several different ways of representing the data to no avail. It seems no matter what I try, Jackson wants to return a list of strings instead of a list of enums.

So my question is this:

How can I make Jackson (version 2.9.4) JSON properly deserialize a list of enum values in a way that is compatible with my single "Object getConfigValue()" method?

Upvotes: 2

Views: 4842

Answers (1)

Bluurr
Bluurr

Reputation: 457

The following will provide the correct binding for your enum.

public List<SystemMode> getConfigValue(String path)
{
    JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
    return objectMapper.convertValue(node, new TypeReference<List<SystemMode>>(){});
}

The second option is to convert the list of String yourself, for example:

List<SystemMode> result = jsonResult.stream().map(SystemMode::valueOf).collect(Collectors.toList());

Third option:

public <T>List<T> getConfigValue(String path, Class<T> type)
{
    JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
    CollectionType toType = 
    objectMapper.getTypeFactory().constructCollectionType(List.class, type);
    return objectMapper.convertValue(node, toType);
}

Upvotes: 2

Related Questions