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]
我有一个 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]