如何使用另一个字段提供的动态类编写自定义Jackson取消序列化程序



我有这样的对象:

{
"type": "MY_TYPE",
"value": "SomeCustomValue"
}

字段Value的实际类型可以更改,但由于字段type被映射到Java枚举,我可以知道这种类型。

关联的POJO如下:

public class MyCustomObject<T> {
public MyTypeEnum type;
public T value;
public MyCustomObject(MyTypeEnum type, T value) {
this.type = type;
this.value = value;
}
}

还有我的自定义反序列化程序:

public class MyCustomObjectDeserializer extends JsonDeserializer<MyCustomObject<?>> {
public MyCustomObject<?> deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
JsonNode node = jsonParser.readValueAsTree();
MyTypeEnum type = MyTypeEnum.valueOf(node.get("type").asText());
//CommonObjectMapper.get() returns a jackson object mapper
Object value = CommonObjectMapper.get().convertValue(node.get("value").asText(), type.getType());
return new MyCustomObject<>(data, value);
}
}

正如您所看到的,我可以从type.getType中获得实际类型,但随后我必须获得另一个对象映射器来对我的value字段进行实际的取消序列化。

这是有效的,但我很确定这不是正确的方法吗?

您可以通过使用JsonParser的编解码器并用TreeTraversingParser:包装value属性的节点来重用已经注册的反序列化程序

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.TreeTraversingParser;
import java.io.IOException;
public class MyCustomObjectDeserializer extends StdDeserializer<MyCustomObject<?>> {
protected MyCustomObjectDeserializer() {
super(MyCustomObject.class);
}
@Override
public MyCustomObject<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.readValueAsTree();
MyTypeEnum type = MyTypeEnum.valueOf(node.get("type").asText());
Object value = p.getCodec().readValue(new TreeTraversingParser(node.get("value"), p.getCodec()), type.getType());
return new MyCustomObject<>(type, value);
}
}

最新更新