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

时间:2022-02-22 18:02:10

I need to add new property to an object, when serializing to JSON. The value for the property is calculated on runtime and does not exist in the object. Also the same object can be used for creation of different JSON with different set ot fields (kind of having a base class with subclasses, but I don't want to create ones just for JSON generation).

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

What is the best way of doing that, which doesn't involve creation of custom serializer class, which will take care of serializing of whole set of object's fields? Or may be it is possible to inherit some "basic" serializer, and simply take it's output and add new field to it somehow?

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

I learned about mixins, and looks like it is possible to rename/hide some fields, however it seems not be possible to add an extra one.

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

2 个解决方案

#1


8  

Can you not just add a method in value class? Note that it does not have to be either public, or use getter naming convention; you could do something like:

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

Otherwise you could convert POJO into JSON Tree value:

否则,您可以将POJO转换为JSON树值:

JsonNode tree = mapper.valueToTree(value);

and then modify it by adding properties etc.

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

#2


1  

One option is to add a field for this property and set it on the object before writing to JSON. A second option, if the property can be computed from other object properties you could just add a getter for it, for example:

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

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

And even though there's no matching field Jackson will automatically call this getter while writing the JSON and it will appear as fullName in the JSON output. If that won't work a third option is to convert the object to a map and then manipulate it however you need:

即使没有匹配字段,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);

You're question didn't mention unmarshalling but if you need to do that as well then the first option would work fine but the second two would need some tweaking.

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

And as for writing different fields of the same object it sounds like a job for @JsonView

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

#1


8  

Can you not just add a method in value class? Note that it does not have to be either public, or use getter naming convention; you could do something like:

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

Otherwise you could convert POJO into JSON Tree value:

否则,您可以将POJO转换为JSON树值:

JsonNode tree = mapper.valueToTree(value);

and then modify it by adding properties etc.

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

#2


1  

One option is to add a field for this property and set it on the object before writing to JSON. A second option, if the property can be computed from other object properties you could just add a getter for it, for example:

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

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

And even though there's no matching field Jackson will automatically call this getter while writing the JSON and it will appear as fullName in the JSON output. If that won't work a third option is to convert the object to a map and then manipulate it however you need:

即使没有匹配字段,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);

You're question didn't mention unmarshalling but if you need to do that as well then the first option would work fine but the second two would need some tweaking.

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

And as for writing different fields of the same object it sounds like a job for @JsonView

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