![](/img/trans.png)
[英]How to use regular JSON interpretation inside of a Jackson custom JSON deserializer
[英]How use jackson ObjectMapper inside custom deserializer?
我尝试编写自定义 jackson 解串器。 我想“查看”一个字段并对 class 执行自动反序列化,请参见下面的示例:
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);
}
}
}
波霍斯:
public class MyFailure implements MyInterface {}
public class MySuccess implements MyInterface {}
@JsonDeserialize(using = MyDeserializer.class)
public interface MyInterface {}
我得到了StackOverflowError
。 了解codec.treeToValue
调用相同的反序列化器。 有没有办法在客户解串器中使用codec.treeToValue
或ObjectMapper.readValue(String,Class<T>)
?
直接的问题似乎是@JsonDeserialize(using=...)
被用于MyInterface和MyInterface本身的实现:因此无限循环。
你可以解决这个问题,重写每个实现中的设置:
@JsonDeserialize(using=JsonDeserializer.None.class)
public static class MySuccess implements MyInterface {
}
或者通过使用模块而不是注释来配置反序列化(并从MyInterface中删除注释):
mapper.registerModule(new SimpleModule() {{
addDeserializer(MyInterface.class, new MyDeserializer());
}});
另外,您还可以考虑扩展StdNodeBasedDeserializer
以实现基于JsonNode的反序列化。 例如:
@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)
为了使用自己ObjectMapper
自定义解串器里面,您可以使用杰克逊混合式注解 ( 在 DefaultJsonDeserializer
接口 )从动态删除自定义解串器POJO
类,避免StackOverflowError
,否则将被抛出的结果objectMapper.readValue(JsonParser, Class<T>)
。
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
}
}
我找到了在自定义反序列化中使用 object 映射器的解决方案
public class DummyDeserializer extends JsonDeserializer<Dummy> {
@Override
public Dummy deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
ObjectMapper om = new ObjectMapper();
om.addMixIn(NexusAccount.class, DefaultJsonDeserializer.class);
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
String serviceType = node.path("serviceType").asText();
switch (serviceType) {
case "Dummy1":
return om.treeToValue(node, Dumm1.class);
case "Dummy2":
return om.treeToValue(node, Dummy2.class);
case "Dummy3":
return om.treeToValue(node, Dummy3.class);
default:
throw new IllegalArgumentException("Unknown Dummy type");
}
}
@JsonDeserialize
private interface DefaultJsonDeserializer {
// Reset default json deserializer
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.