Java 枚举字段上的 @JsonValue,当此枚举用作映射键时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22023377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@JsonValue on an enum field, when this enum used as map key
提问by acemrek
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);
}
}
I have the above enumeration with
我有上面的枚举
@JsonValue public String getValue(){ return value; }
@JsonValue public String getValue(){ 返回值;}
part and a sample test class like...
部分和示例测试类,如...
public class 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(); } } }
公共类 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(); } } }
This test class prints out
这个测试类打印出来
["0500","0402"]
{"2":"0402","1":"0500"}
{"TEMPERATURE":"2","ALARMED":"1"}
@JsonValue is not working when used on an enum field which is a key of map.
@JsonValue 在作为地图键的枚举字段上使用时不起作用。
Is there a way to use this enum as key when serializing maps?
有没有办法在序列化地图时使用这个枚举作为键?
Thanks.
谢谢。
采纳答案by Sotirios Delimanolis
Hymanson uses a MapSerializer
to serialize Map
types and uses a StdKeySerializer
to serialize the keys. It's implemented as
Hymanson 使用 aMapSerializer
序列化Map
类型并使用 aStdKeySerializer
序列化键。它被实现为
@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());
}
}
which you can see just gets the toString()
value of your object. So you can override the toString()
method in your enum
as such
您可以看到它只是获取toString()
对象的值。所以你可以像这样覆盖你的toString()
方法enum
public String toString() {
return getValue();
}
The @JsonValue
becomes useless.
将@JsonValue
变得无用。
Alternatively, if you need the toString()
to remain the same (or default), you can create a custom type that wraps your Map
或者,如果您需要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/HymanSON-765
@JsonSerialize(keyUsing = ClusterTypeKeySerializer.class)
public Map<ClusterType, String> getMap() {
return map;
}
public void setMap(Map<ClusterType, String> map) {
this.map = map;
}
}
and uses a custom JsonSerializer
并使用自定义 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());
}
}
that uses the ClusterType#getValue()
method. Again, we don't use @JsonValue
.
使用该ClusterType#getValue()
方法。同样,我们不使用@JsonValue
.
回答by StaxMan
Actually, I think this is just a feature that hasn't been added, as per:
实际上,我认为这只是一个尚未添加的功能,如下所示:
https://github.com/FasterXML/Hymanson-databind/issues/47
https://github.com/FasterXML/Hymanson-databind/issues/47
so whereas @JsonValue
works fine for Enums with respect to deserialization, it does not yet work for serialization. Project is always open for contributions, if anyone has time to tackle this -- it should not be big undertaking.
因此,虽然@JsonValue
在反序列化方面对 Enums 工作正常,但它还不适用于序列化。项目总是对贡献开放,如果有人有时间解决这个问题——它不应该是一项艰巨的任务。