【问题标题】:@JsonValue on an enum field, when this enum used as map key枚举字段上的@JsonValue,当此枚举用作映射键时
【发布时间】:2014-03-28 05:13:51
【问题描述】:
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 在作为映射键的枚举字段上使用时不起作用。

有没有办法在序列化地图时使用这个枚举作为键?

谢谢。

【问题讨论】:

    标签: java enums jackson


    【解决方案1】:

    其实我认为这只是一个没有添加的功能,按:

    https://github.com/FasterXML/jackson-databind/issues/47

    所以虽然@JsonValue 在反序列化方面对 Enums 工作得很好,但它还不适用于序列化。如果有人有时间解决这个问题,项目总是开放供贡献的——这应该不是什么大工程。

    【讨论】:

      【解决方案2】:

      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() 值。因此,您可以像这样覆盖 enum 中的 toString() 方法

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-13
        • 2020-01-15
        • 1970-01-01
        • 2019-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多