20

在序列化为 JSON 时,我需要向对象添加新属性。该属性的值是在运行时计算的,并且不存在于对象中。同样的对象也可以用于创建具有不同集合的字段的不同 JSON(有点具有带有子类的基类,但我不想创建仅用于 JSON 生成的对象)。

这样做的最佳方法是什么,它不涉及创建自定义序列化程序类,它将负责序列化整组对象的字段?或者可能继承一些“基本”序列化程序,并简单地获取它的输出并以某种方式添加新字段?

我了解了mixins,看起来可以重命名/隐藏某些字段,但似乎无法添加额外的字段。

4

3 回答 3

15

你不能只在值类中添加一个方法吗?请注意,它不必是公开的,也不必使用 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);

然后通过添加属性等来修改它。

于 2013-01-16T21:21:21.893 回答
3

一种选择是为此属性添加一个字段并将其设置在对象上,然后再写入 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

于 2013-01-17T01:02:34.343 回答
1

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 的末尾保留传输属性。

于 2021-05-11T20:11:43.960 回答