Я запускаю Spring Boot с Джексоном 2.10.3.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.3</version>
</dependency>
Мое входное значение представляет собой json представление сериализованного объекта, в моем случае F C. java Когда При создании Mapper регистрируется новый CustomerFCDeserializer.
mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(FC.class, new CustomFCDeserializer(fcFactory));
mapper.registerModule(module);
CustomFCDeserializer предназначен для инициализации объекта F C, в который сериализованный объект должен быть десериализован. fc = super.deserialize(parser, dc, fc);
Обычно я просто десериализовал бы его, но в этом конкретном c случае конструктор по умолчанию не может быть вызван, вместо этого объект нуждается в некоторой другой инициализации, как это делает FcFactory. Таким образом, в объекте, возвращаемом фабрикой, будут установлены также сериализованные поля.
public class CustomFCDeserializer extends StdDeserializer<FC> {
private final FCFactory fcFactory;
public CustomFCDeserializer(FCFactory fcFactory) {
super(FC.class);
this.fcFactory = fcFactory;
}
@Override
public FC deserialize(JsonParser parser, DeserializationContext dc) throws IOException, JsonProcessingException {
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
JsonNode idNode = node.get("id");
long id = idNode.asLong(0);
FC fc = fcFactory.getFCById(id); //<!--- create my object
//set values on prev created fc object
fc = super.deserialize(parser, dc, fc); //<!-- pollute it
return fc;
}
}
Выполнение этого примера рекурсивно вызовет deserialize, super.deserialize и, наконец, снова десериализацию, которая завершается неудачей при изменении структуры.
java.lang.NullPointerException: null
at objectMapper.CustomFcDeserializer.deserialize(CustomFcDeserializer.java:38) ~[classes/:na]
at objectMapper.CustomFcDeserializer.deserialize(CustomFcDeserializer.java:16) ~[classes/:na]
at com.fasterxml.jackson.databind.JsonDeserializer.deserialize(JsonDeserializer.java:129) ~[jackson-databind-2.9.0.jar:2.9.0]
at objectMapper.CustomFcDeserializer.deserialize(CustomFcDeserializer.java:51) ~[classes/:na]
at objectMapper.CustomFcDeserializer.deserialize(CustomFcDeserializer.java:16) ~[classes/:na]
[...]
Есть ли лучший способ, чем решить эту проблему кучей операторов if? Или это более разумный способ загрязнения существующего объекта? deserialize(JsonParser p, DeserializationContext ctxt, T intoValue)
, кажется, будет в порядке, поскольку требуется intoValue
, но я десериализирую объект, а не коллекцию или карту. Кстати, мой объект не имеет и не имеет неизменных членов.
com.fasterxml.jackson.databind.JsonDeserializer
public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue) throws IOException
Alternate deserialization method (compared to the most commonly used, deserialize(JsonParser, DeserializationContext)), which takes in initialized value instance, to be configured and/or populated by deserializer. Method is not necessarily used (or supported) by all types (it will not work for immutable types, for obvious reasons): most commonly it is used for Collections and Maps. It may be used both with "updating readers" (for POJOs) and when Collections and Maps use "getter as setter".
Throws: IOException