在序列化为 JSON 时,我需要向对象添加新属性。该属性的值是在运行时计算的,并且不存在于对象中。同样的对象也可以用于创建具有不同集合的字段的不同 JSON(有点具有带有子类的基类,但我不想创建仅用于 JSON 生成的对象)。
这样做的最佳方法是什么,它不涉及创建自定义序列化程序类,它将负责序列化整组对象的字段?或者可能继承一些“基本”序列化程序,并简单地获取它的输出并以某种方式添加新字段?
我了解了mixins,看起来可以重命名/隐藏某些字段,但似乎无法添加额外的字段。
在序列化为 JSON 时,我需要向对象添加新属性。该属性的值是在运行时计算的,并且不存在于对象中。同样的对象也可以用于创建具有不同集合的字段的不同 JSON(有点具有带有子类的基类,但我不想创建仅用于 JSON 生成的对象)。
这样做的最佳方法是什么,它不涉及创建自定义序列化程序类,它将负责序列化整组对象的字段?或者可能继承一些“基本”序列化程序,并简单地获取它的输出并以某种方式添加新字段?
我了解了mixins,看起来可以重命名/隐藏某些字段,但似乎无法添加额外的字段。
你不能只在值类中添加一个方法吗?请注意,它不必是公开的,也不必使用 getter 命名约定;您可以执行以下操作:
public class MyStuff {
// ... the usual fields, getters and/or setters
@JsonProperty("sum") // or whatever name you need in JSON
private int calculateSumForJSON() {
return 42; // calculate somehow
}
}
否则,您可以将 POJO 转换为 JSON Tree 值:
JsonNode tree = mapper.valueToTree(value);
然后通过添加属性等来修改它。
一种选择是为此属性添加一个字段并将其设置在对象上,然后再写入 JSON。第二种选择,如果可以从其他对象属性计算属性,则可以为其添加一个 getter,例如:
public String getFullName() {
return getFirstName() + " " + getLastName();
}
即使没有匹配的字段,Jackson 也会在编写 JSON 时自动调用这个 getter,它会fullName
在 JSON 输出中出现。如果这不起作用,第三种选择是将对象转换为地图,然后根据需要对其进行操作:
ObjectMapper mapper //.....
MyObject o //.....
long specialValue //.....
Map<String, Object> map = mapper.convertValue(o, new TypeReference<Map<String, Object>>() { });
map.put("specialValue", specialValue);
你的问题没有提到解组,但如果你也需要这样做,那么第一个选项可以正常工作,但后两个需要一些调整。
至于为同一个对象编写不同的字段,这听起来像是一项工作@JsonView
2021年召唤...
我发现这样做的最简单方法是@JsonUnwrapped
:
public class Envelope<T> {
@JsonUnwrapped // content's fields are promoted alongside the envelope's
public T content;
// Transmission specific fields
public String url;
public long timestamp;
}
只要Envelope's
字段名不与content
. 还有一个很好的特性是在序列化 JSON 的末尾保留传输属性。