Как добавить дополнительные поля в объект во время сериализации Джексона json?
Мне нужно добавить новое свойство к объекту при сериализации в JSON. Значение свойства вычисляется во время выполнения и не существует в объекте. Также один и тот же объект может использоваться для создания разных JSON с разными полями set ot (вроде базового класса с подклассами, но я не хочу создавать их только для генерации JSON).
Каков наилучший способ сделать это, что не связано с созданием пользовательского класса сериализатора, который позаботится о сериализации всего набора полей объекта? Или, может быть, можно наследовать некоторый "базовый" сериализатор, и просто взять его вывод и добавить к нему какое-то новое поле?
Я узнал о mixins и выглядит так, что можно переименовать/скрыть некоторые поля, однако, кажется, не возможно добавить лишний.
Ответы
Ответ 1
Не можете ли вы добавить метод в класс значений? Обратите внимание, что это не должно быть публичным или использовать соглашение об именовании получателя; вы можете сделать что-то вроде:
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);
а затем измените его, добавив свойства и т.д.
Ответ 2
Один из вариантов - добавить поле для этого свойства и установить его на объект перед записью в JSON. Второй вариант, если свойство можно вычислить из других свойств объекта, вы можете просто добавить для него геттер, например:
public String getFullName() {
return getFirstName() + " " + getLastName();
}
И даже если нет соответствующего поля, Джексон будет автоматически вызывать этот getter при записи JSON, и он будет отображаться как fullName
на выходе JSON. Если это не сработает, третий вариант состоит в том, чтобы преобразовать объект в карту и затем манипулировать им, но вам нужно:
ObjectMapper mapper //.....
MyObject o //.....
long specialValue //.....
Map<String, Object> map = mapper.convertValue(o, new TypeReference<Map<String, Object>>() { });
map.put("specialValue", specialValue);
Вы сомневаетесь, что не упоминаете unmarshalling, но если вам нужно это сделать, тогда первый вариант будет работать нормально, но второй второй потребует некоторой настройки.
А что касается написания разных полей одного и того же объекта, это звучит как задание для @JsonView