杰克逊:将枚举值序列化和反序列化为整数

问题描述 投票:19回答:5

考虑以下枚举和类:

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

这个输出对我来说不好,因为而不是"OFF"的字符串state,我希望它是1,这是OFF在enum State中的序数值。

所以我想得到的实际结果是:

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

是否有一些优雅的方式让它表现得这样?

java json serialization enums jackson
5个回答
36
投票

它应该通过指定JsonValue映射器来工作。

public enum State {
    ON,
    OFF,
    UNKNOWN;

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

这也适用于反序列化,如@JsonValue注释的Javadoc所述:

注意:当用于Java枚举时,另外一个特性是注释方法返回的值也被认为是反序列化的值,而不仅仅是要序列化的JSON字符串。这是可能的,因为Enum值的集合是常量并且可以定义映射,但是对于POJO类型通常不能完成;因此,这不用于POJO反序列化


11
投票

你可以使用设置

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/的小费


2
投票

如果你想打印枚举的序数你可以改变你的构造函数接受int而不是State然后在你调用Machine时你可以用以下方式构造它:

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

这将获得传入状态的枚举序号值并打印以下内容

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


1
投票

为了完成,我发布另一种方式:自定义序列化器:

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(){...}
}

0
投票

另一种方式:

public enum State {

    @JsonProperty("0")
    ON,

    @JsonProperty("1")
    OFF,

    @JsonProperty("2")
    UNKNOWN
}

但是,这将生成{"state" : "1"}而不是{"state" : 1}(字符串,而不是数字)。在大多数情况下,没关系


0
投票

你可以这样使用

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonFormat(shape = JsonFormat.Shape.NUMBER)
public enum State {
       ON,
       OFF,
       UNKNOWN
}
© www.soinside.com 2019 - 2024. All rights reserved.