Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize JSON using GSON to Enum

Tags:

java

enums

gson

My goal is to parse a JSON file or part of it to an Enum class in Java. I can do it easily, but for debugging reasons I would like to include a default value as well.

public enum MyEnum {
    @SerializedName("texts")
    TEXTS,
    @SerializedName("buttons")
    BUTTONS,
    @SerializedName("inputs")
    INPUTS,
    DEFAULT
}

So if I try to parse this JSON (using a wrapper class):

{enum: "buttons"}

I would get MyEnum.BUTTONS, but if I try to parse:

{enum: "divider"}

I would still like to know the value. I would like to map all values (e.g. "divider", "line", "color",...) to DEFAULT (maintaining the String which mapped to the DEFAULT value). Would it be possible to save value "divider" to MyEnum.DEFAULT property?

like image 864
urgas9 Avatar asked Nov 09 '22 16:11

urgas9


1 Answers

Implement a custom JsonDeserializer and install it using GsonBuilder.registerTypeAdapter. Your enum implementation could then be implemented as follows:

public enum MyEnum {
    TEXTS ("texts"),
    BUTTONS("buttons"),
    INPUTS("inputs"),
    DEFAULT(null);

    private String text;

    private MyEnum (String text) {
        this.text = text;
    }

    public String getValue () {
        return text;
    }

    public static MyEnum mapFrom (String serialized) {
        if (serialized == null) {
            DEFAULT.text = null;
            return DEFAULT;
        }
        for (MyEnum inst : MyEnum.values()) {
            if (serialized.equals(inst.getValue())) {
                return inst;
            }
        }
        DEFAULT.text = serialized;
        return DEFAULT;
    }
}

The implementation of your deserializer (and serializer, too) then uses the mapFrom method of your enum. The side effect is that the DEFAULT instance always has the latest value on a global scope, so I wouldn't recommend this approach if used wider than debugging, and to be honest I wouldn't expect another programmer to understand why I wrote this.

However, if you extract the serialized forms of your enums out of the enum definition, then in your deserializer you need to implement a switch that decides which enum to deserialize into. If you also separate your debugging code and call it from your deserializer, you don't need the serialized form in your enum anymore. Moreover, you separate different functionality - the Single Responsibility Principle.

The only other option left is using a non-enum class, so you can instantiate new objects upon deserialization time.

like image 62
Timmos Avatar answered Nov 14 '22 23:11

Timmos