Java 如何在自定义反序列化程序中使用jackson ObjectMapper?
我尝试编写自定义的jackson反序列化程序。我希望“查看”一个字段并对类执行自动反序列化,请参见下面的示例:Java 如何在自定义反序列化程序中使用jackson ObjectMapper?,java,json,jackson,json-deserialization,Java,Json,Jackson,Json Deserialization,我尝试编写自定义的jackson反序列化程序。我希望“查看”一个字段并对类执行自动反序列化,请参见下面的示例: import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.Dese
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.mypackage.MyInterface;
import com.mypackage.MyFailure;
import com.mypackage.MySuccess;
import java.io.IOException;
public class MyDeserializer extends JsonDeserializer<MyInterface> {
@Override
public MyInterface deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec codec = jp.getCodec();
JsonNode node = codec.readTree(jp);
if (node.has("custom_field")) {
return codec.treeToValue(node, MyFailure.class);
} else {
return codec.treeToValue(node, MySuccess.class);
}
}
}
我得到了
堆栈溢出错误。在理解中,codec.treeToValue
调用相同的反序列化程序。有没有一种方法可以在custome反序列化程序中使用codec.treeToValue
或ObjectMapper.readValue(String,Class)
呢?眼前的问题似乎是@jsondeseligate(using=…)
正在为MyInterface的实现以及MyInterface本身挑选:因此产生了无休止的循环
您可以通过覆盖每个实现中的设置来解决此问题:
@JsonDeserialize(using=JsonDeserializer.None.class)
public static class MySuccess implements MyInterface {
}
或者使用模块而不是注释来配置反序列化(并从MyInterface中删除注释):
在一个旁注中,您还可以考虑扩展<代码> STDNODEBASED反序列化器< /C>以实现基于JSONNoCT的反序列化。例如:
@Override
public MyInterface convert(JsonNode root, DeserializationContext ctxt) throws IOException {
java.lang.reflect.Type targetType;
if (root.has("custom_field")) {
targetType = MyFailure.class;
} else {
targetType = MySuccess.class;
}
JavaType jacksonType = ctxt.getTypeFactory().constructType(targetType);
JsonDeserializer<?> deserializer = ctxt.findRootValueDeserializer(jacksonType);
JsonParser nodeParser = root.traverse(ctxt.getParser().getCodec());
nodeParser.nextToken();
return (MyInterface) deserializer.deserialize(nodeParser, ctxt);
}
@覆盖
公共MyInterface convert(JsonNode根,反序列化上下文ctxt)引发IOException{
java.lang.reflect.Type targetType;
if(root.has(“自定义_字段”)){
targetType=MyFailure.class;
}否则{
targetType=MySuccess.class;
}
JavaType jacksonType=ctxt.getTypeFactory().constructType(targetType);
JsonDeserializer反序列化程序=ctxt.findRootValueDeserializer(jacksonType);
JsonParser nodeParser=root.traverse(ctxt.getParser().getCodec());
nodeParser.nextToken();
返回(MyInterface)反序列化程序;
}
此自定义反序列化程序有很多改进,特别是在跟踪反序列化上下文等方面,但这应该提供您所要求的功能。这为我带来了窍门:
ctxt.readValue(node, MyFailure.class)
为了在自定义反序列化程序中使用您自己的ObjectMapper
,您可以使用(DefaultJsonDeserializer
接口)从POJO
类中动态删除自定义反序列化程序,避免objectMapper.readValue(JsonParser,Class)
引发的StackOverflowError
公共类MyDeserializer扩展JsonDeserializer{
私有静态最终ObjectMapper ObjectMapper=新ObjectMapper();
静止的{
addMixIn(MySuccess.class,DefaultJsonDeserializer.class);
addMixIn(MyFailure.class、DefaultJsonDeserializer.class);
}
@凌驾
公共MyInterface反序列化(JsonParser jp,反序列化上下文ctxt)引发IOException,JsonProcessingException{
if(jp.getCodec().readTree(jp).has(“自定义_字段”)){
返回objectMapper.readValue(jp,MyFailure.class);
}否则{
返回objectMapper.readValue(jp,MySuccess.class);
}
}
@JsonDeserialize
专用接口DefaultJsonDeserializer{
//重置默认json反序列化程序
}
}
您能提供MCVE吗?我曾尝试扩展StdNodeBasedDeserializer,但要求我不提供参数构造函数。如果我这样做,_treedSerializer字段为空…@araqnid你能详细说明你提到的改进吗?
@Override
public MyInterface convert(JsonNode root, DeserializationContext ctxt) throws IOException {
java.lang.reflect.Type targetType;
if (root.has("custom_field")) {
targetType = MyFailure.class;
} else {
targetType = MySuccess.class;
}
JavaType jacksonType = ctxt.getTypeFactory().constructType(targetType);
JsonDeserializer<?> deserializer = ctxt.findRootValueDeserializer(jacksonType);
JsonParser nodeParser = root.traverse(ctxt.getParser().getCodec());
nodeParser.nextToken();
return (MyInterface) deserializer.deserialize(nodeParser, ctxt);
}
ctxt.readValue(node, MyFailure.class)
public class MyDeserializer extends JsonDeserializer<MyInterface> {
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.addMixIn(MySuccess.class, DefaultJsonDeserializer.class);
objectMapper.addMixIn(MyFailure.class, DefaultJsonDeserializer.class);
}
@Override
public MyInterface deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
if (jp.getCodec().<JsonNode>readTree(jp).has("custom_field")) {
return objectMapper.readValue(jp, MyFailure.class);
} else {
return objectMapper.readValue(jp, MySuccess.class);
}
}
@JsonDeserialize
private interface DefaultJsonDeserializer {
// Reset default json deserializer
}
}