我有这样的对象:
{
"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);
}
}