首页 > 解决方案 > 如何将多个 JsonProperty 映射到单个变量?

问题描述

我有一个 PrintType 枚举,我想将空字符串反序列化为 DEFAULT 类型;

@JsonProperty("default", "")
DEFAULT

有没有办法将多个 JsonProperty 映射到单个变量?

My PrintType enum;

public enum PrintType{

    @JsonProperty("default")
    DEFAULT,


    ....

}

标签: javajackson

解决方案


首先,请注意JsonProperty用于表示属性的名称,而不是它们的值。在这个例子中,DEFAULT是枚举的一个元素,而不是它的属性/字段/方法,所以这个注释是不合适的。

要从多个可能的值反序列化一个枚举元素,您需要创建一个简单JsonDeserializer的来执行映射。例如:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;

public class PrintTypeDeserializer extends JsonDeserializer<PrintType> {

  private static final Set<String> DEFAULT_VALUES = new HashSet<>(Arrays.asList("", "default"));

  @Override
  public PrintType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
    final String value = jsonParser.getValueAsString();
    if (DEFAULT_VALUES.contains(value)) {
      return PrintType.DEFAULT;
    }
    return PrintType.valueOf(value);
  }

}

要使用此反序列化器,请在PrintType要反序列化的字段上声明它:

public class MyObj {

  @JsonProperty("print_type")
  @JsonDeserialize(using = PrintTypeDeserializer.class)
  private PrintType printType;

}

PrintType(但如果出现在不同的对象中,则需要复制)

或在各自的范围内注册解串器ObjectMapper

private static ObjectMapper initObjectMapper() {
  final ObjectMapper mapper = new ObjectMapper();
  final SimpleModule module = new SimpleModule();
  module.addDeserializer(PrintType.class, new PrintTypeDeserializer());
  mapper.registerModule(module);
  return mapper;
}

现在,一个简短的测试用例:

public enum PrintType {

  DEFAULT, TYPE_A, TYPE_B;

}

@Test
public void deserializeEnum() {
  final List<String> jsons = Arrays.asList(
      "{ \"print_type\": null }",
      "{ \"print_type\": \"\" }",
      "{ \"print_type\": \"default\" }",
      "{ \"print_type\": \"DEFAULT\" }",
      "{ \"print_type\": \"TYPE_A\" }",
      "{ \"print_type\": \"TYPE_B\" }"
  );

  final ObjectMapper mapper = initObjectMapper();

  jsons.stream().forEach(json -> {
    try {
      System.out.println(mapper.readValue(json, MyObj.class));
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  });

}

// output:
//  MyObj(printType=null)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=TYPE_A)
//  MyObj(printType=TYPE_B)

推荐阅读