public enum ClusterType {
    TEMPERATURE("0402"),
    HUMIDITY("0405"),
    ENERGY_DETAILS("0702"),
    SMART_SOCKET_STATUS("0006"),
    ALARMED("0500");

    private String value = null;

    ClusterType(String byteStr) {
        this.value = byteStr;
    }

    @JsonCreator
    public static ClusterType fromValue(final String val){
        return (ClusterType) CollectionUtils.find(Arrays.asList(ClusterType.values()), new Predicate() {
            public boolean evaluate(Object object) {
                ClusterType candidate = (ClusterType) object;
                return StringUtils.equals(candidate.value, val);
            }
        });
    }

    @JsonValue
    public String getValue(){
        return value;
    }

    public byte[] get() {
        return ByteUtils.hexStringToByteArray(value);
    }

    public boolean equals(String cluster) {
        return StringUtils.equals(cluster, value);
    }
}

我有以上列举

@JsonValue
公共字符串getValue(){
返回值
}

部分和示例测试类,例如...

公共课Foo {
public static void main(String[] args) {
    try {
        ObjectMapper objectMapper = new ObjectMapper();

        ClusterType []arrayRep = new ClusterType[]{ClusterType.ALARMED, ClusterType.TEMPERATURE};

        Map<String, ClusterType>  mapRepAsValue = new HashMap<>();
        mapRepAsValue.put("1", ClusterType.ALARMED);
        mapRepAsValue.put("2", ClusterType.TEMPERATURE);

        Map<ClusterType, String>  mapRepAsKey = new HashMap<>();
        mapRepAsKey.put(ClusterType.ALARMED, "1");
        mapRepAsKey.put(ClusterType.TEMPERATURE, "2");

        System.out.println(objectMapper.writeValueAsString(arrayRep));
        System.out.println(objectMapper.writeValueAsString(mapRepAsValue));
        System.out.println(objectMapper.writeValueAsString(mapRepAsKey));

    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
} }

该测试类打印出来
["0500","0402"]
{"2":"0402","1":"0500"}
{"TEMPERATURE":"2","ALARMED":"1"}

在作为映射键的枚举字段上使用时,@ JsonValue不起作用。

序列化地图时,有没有办法将此枚举用作键?

谢谢。

最佳答案

Jackson使用MapSerializer序列化Map类型,并使用StdKeySerializer序列化密钥。它实现为

@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
    throws IOException, JsonGenerationException
{
    if (value instanceof Date) {
        provider.defaultSerializeDateKey((Date) value, jgen);
    } else {
        jgen.writeFieldName(value.toString());
    }
}

您可以看到它只是获取对象的toString()值。因此,您可以像这样在toString()中覆盖enum方法
public String toString() {
    return getValue();
}
@JsonValue变得无用。

另外,如果您需要toString()保持相同(或默认),则可以创建一个自定义类型来包装Map
class CustomType {
    private Map<ClusterType, String> map;

    @JsonAnyGetter // necessary to unwrap the Map to the root object, see here: http://jira.codehaus.org/browse/JACKSON-765
    @JsonSerialize(keyUsing = ClusterTypeKeySerializer.class)
    public Map<ClusterType, String> getMap() {
        return map;
    }

    public void setMap(Map<ClusterType, String> map) {
        this.map = map;
    }
}

并使用自定义的JsonSerializer
class ClusterTypeKeySerializer extends StdSerializer<ClusterType> {

    protected ClusterTypeKeySerializer() {
        super(ClusterType.class);
    }

    @Override
    public void serialize(ClusterType value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonGenerationException {
        jgen.writeFieldName(value.getValue());
    }

}

使用ClusterType#getValue()方法。同样,我们不使用@JsonValue

07-26 00:47