Serializing/deserializing Jackson 中的别名基元没有太多样板

Serializing/deserializing aliased primitives in Jackson without too much boilerplate

我有一个 class 我想将 Java 反序列化为 class。 class 属性之一本身就是一个可序列化的 class,它有一个原始 (String) 参数,实际上代表一个别名字符串,即一个带有一些额外内容的字符串,以确保它出现在正确的格式。这在各种应用程序(例如标识符)中很有用,在这种情况下,它是一个必须具有特定表示的 Cron 字符串。所以我有

class ScheduleConfigurations {
    private Cron cron;
    private Set<Cron> overrides;
    // other attributes, getters/setters, constructor
}


class Cron {
    private String cronString;

    private void validate() { // validates string has correct representation }
    // getters, setters, constructor
}

显然,标准的 Jackson 解串器需要 JSON 格式

{
    "cron": {
        "cronString": "someCronString",
    "overrides": [
        { "cronString": "someCronString1" },
        { "cronString": "someCronString2" }
    ]
}

然而,Cron class 显然只是一个别名字符串。我希望上面的 serialized/deserialized 为

{
    "cron": "someCronString",
    "overrides": ["someCronString1", "someCronString2"]
}

我可以使用带有一堆样板的自定义序列化程序来实现这一点,但我正在寻找一种优雅的方式来告诉 Jackson "hey, this class has one String attribute, just pass through it and treat its serialized representation as its only attribute"。

由于您希望将整个对象序列化(反)为字符串,因此非常简单:

@JsonSerialize(using = ToStringSerializer.class)
class Cron {
    private String cronString;
    public Cron(String cronString) { // Called by Jackson when deserializing from JSON string
        this.cronString = cronString;
    }
    @Override
    public String toString() { // Called by Jackson when serializing to JSON
        return this.cronString;
    }
}

由于 class 只是字符串的包装器,您甚至不需要 getter、setter 或其他构造函数,甚至不需要其他 Java 代码,当然你仍然可以拥有它们。

测试

ScheduleConfigurations configObj = new ScheduleConfigurations();
configObj.setCron(new Cron("someCronString"));
configObj.setOverrides(new LinkedHashSet<>(Arrays.asList(
        new Cron("someCronString1"), new Cron("someCronString2"))));
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(configObj));
String json = "{\r\n" + 
              "  \"cron\" : \"someCronString\",\r\n" + 
              "  \"overrides\" : [ \"someCronString1\", \"someCronString2\" ]\r\n" + 
              "}";
ScheduleConfigurations configObj = new ObjectMapper().readValue(json, ScheduleConfigurations.class);
System.out.println("cron = " + configObj.getCron());
System.out.println("overrides = " + configObj.getOverrides());

输出

{
  "cron" : "someCronString",
  "overrides" : [ "someCronString1", "someCronString2" ]
}
cron = someCronString
overrides = [someCronString1, someCronString2]