web-dev-qa-db-ja.com

ジャクソン:列挙値を整数としてシリアル化および逆シリアル化します

次の列挙型とクラスを検討してください。

public enum State {
    ON,
    OFF,
    UNKNOWN
}

public class Machine {
    String name;
    int numCores;
    State state;

    public Machine(String name, int numCores, State state) {
        this.name = name;
        this.numCores = numCores;
        this.state = state;
    }
}

そして、次の主な機能を検討してください。

public static void main(String args[]) {
    Machine m = new Machine("Machine 1", 8, OFF);
    ObjectMapper mapper = new ObjectMapper();
    String machineAsJsonString = mapper.writeValueAsString(m);
    System.out.println(machineAsJsonString);
}

現在、このメインの出力は次のとおりです。

{"name" : "Machine 1", "numCores" : 8, "state" : "OFF"}

この出力は、stateの文字列"OFF"の代わりに、_1にしたいと思います。これは、enum OFFStateの序数値です。

だから私が取得したい実際の結果は:

{"name" : "Machine 1", "numCores" : 8, "state" : 1}

このように動作させるエレガントな方法はありますか?

21

JsonValueマッパーを指定することで機能するはずです。

public enum State {
    ON,
    OFF,
    UNKNOWN;

    @JsonValue
    public int toValue() {
        return ordinal();
    }
}  

@JsonValueアノテーションのJavadocに記載されているように、これは逆シリアル化でも機能します。

注:Java列挙型を使用する場合、注釈付きメソッドによって返される値は、シリアライズするJSON文字列だけでなく、デシリアライズする値でもあると見なされるという追加機能があります。列挙値のセットは定数であり、マッピングを定義することは可能ですが、一般にPOJO型に対しては実行できません;そのため、これはPOJOデシリアライゼーションには使用されません

41
user861594

設定を使用できます

objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);

完全なテストケースについては、 https://github.com/FasterXML/jackson-databind/blob/master/src/test/Java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.Java を参照してください

https://righele.it/2016/01/30/jackson-deserialization-from-json-to-Java-enums/ のヒントに感謝します

12
Martin

このように使用できます

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonFormat(shape = JsonFormat.Shape.NUMBER)
public enum State {
       ON,
       OFF,
       UNKNOWN
}
2
dasunse

列挙型の序数を出力する場合は、intの代わりにStateを受け入れるようにコンストラクターを変更し、Machineの呼び出しで構造化できます。次の方法:

Machine m = new Machine("Machine 1", 8, State.OFF.ordinal());

これは、渡された状態の列挙値を取得し、次を出力します

{name='Machine 1', numCores=8, state=1}

2
Tom C

完了のために、別の方法を投稿します:カスタムシリアライザー:

public class StateSerializer extends JsonSerializer<State> {  
    public void serialize(State value, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("id");
        generator.writeNumber(value.getId());
        generator.writeEndObject();
    }
}

@JsonSerialize(using = StateSerializer.class)
public enum State { 
    ...
    public int getId(){...}
}
1
Paco Abato

さらに別の方法:

public enum State {

    @JsonProperty("0")
    ON,

    @JsonProperty("1")
    OFF,

    @JsonProperty("2")
    UNKNOWN
}

ただし、これにより{"state" : "1"} の代わりに {"state" : 1}(数値ではなく文字列)。ほとんどの場合、大丈夫です

0