杰克逊::在序列化中为对象添加额外的字段

时间:2013-01-16 15:44:11

标签: json serialization jackson

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

最好的方法是什么,这不涉及创建自定义序列化程序类,它将负责序列化整个对象的字段集?或者可以继承一些“基本”序列化器,只需将其输出并以某种方式向其添加新字段?

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

3 个答案:

答案 0 :(得分:8)

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

JsonNode tree = mapper.valueToTree(value);

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

答案 1 :(得分:1)

一个选项是为此属性添加一个字段,并在写入JSON之前将其设置在对象上。第二个选项,如果可以从其他对象属性计算属性,则可以为其添加一个getter,例如:

public String getFullName() {
  return getFirstName() + " " + getLastName();
}

即使没有匹配的字段,Jackson在编写JSON时会自动调用此getter,它在JSON输出中显示为fullName。如果这不起作用,第三个选项是将对象转换为地图,然后根据需要对其进行操作:

ObjectMapper mapper //.....
MyObject o //.....
long specialValue //.....
Map<String, Object> map = mapper.convertValue(o, new TypeReference<Map<String, Object>>() { });
map.put("specialValue", specialValue);

你的问题没有提到解组,但是如果你需要这样做那么第一个选项可以正常工作但是后两个需要一些调整。

至于写同一个对象的不同字段,它听起来像是@JsonView

的工作

答案 2 :(得分:0)

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 的末尾。