Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在自定义反序列化程序中使用jackson ObjectMapper?_Java_Json_Jackson_Json Deserialization - Fatal编程技术网

Java 如何在自定义反序列化程序中使用jackson ObjectMapper?

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

我尝试编写自定义的jackson反序列化程序。我希望“查看”一个字段并对类执行自动反序列化,请参见下面的示例:

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
    }

}