java 如何在自定义反序列化器中使用 jackson ObjectMapper?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32551983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How use Hymanson ObjectMapper inside custom deserializer?
提问by Cherry
I try to write custom Hymanson deserializer. I want "look" at one field and perform auto deserialization to class, see example below:
我尝试编写自定义Hyman逊解串器。我想“查看”一个字段并执行自动反序列化到类,请参见下面的示例:
import com.fasterxml.Hymanson.core.JsonParser;
import com.fasterxml.Hymanson.core.JsonProcessingException;
import com.fasterxml.Hymanson.core.ObjectCodec;
import com.fasterxml.Hymanson.databind.DeserializationContext;
import com.fasterxml.Hymanson.databind.JsonDeserializer;
import com.fasterxml.Hymanson.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);
}
}
}
Pojos:
波霍斯:
public class MyFailure implements MyInterface {}
public class MySuccess implements MyInterface {}
@JsonDeserialize(using = MyDeserializer.class)
public interface MyInterface {}
And I got StackOverflowError
. In understand that codec.treeToValue
call same deserializer. Is there a way to use codec.treeToValue
or ObjectMapper.readValue(String,Class<T>)
inside custome deseralizer?
我得到了StackOverflowError
。在理解codec.treeToValue
调用相同的解串器。有没有办法使用codec.treeToValue
或ObjectMapper.readValue(String,Class<T>)
在客户除盐器内使用?
回答by araqnid
The immediate problem seems to be that the @JsonDeserialize(using=...)
is being picked up for your implementations of MyInterface as well as MyInterface itself: hence the endless loop.
眼前的问题似乎@JsonDeserialize(using=...)
是正在为您的 MyInterface 实现以及 MyInterface 本身获取 :因此是无限循环。
You can fix this my overriding the setting in each implementation:
您可以通过覆盖每个实现中的设置来解决此问题:
@JsonDeserialize(using=JsonDeserializer.None.class)
public static class MySuccess implements MyInterface {
}
Or by using a module instead of an annotation to configure the deserialization (and removing the annotation from MyInterface):
或者通过使用模块而不是注释来配置反序列化(并从 MyInterface 中删除注释):
mapper.registerModule(new SimpleModule() {{
addDeserializer(MyInterface.class, new MyDeserializer());
}});
On a side-note, you might also consider extending StdNodeBasedDeserializer
to implement deserialization based on JsonNode. For example:
附带说明一下,您还可以考虑扩展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 HymansonType = ctxt.getTypeFactory().constructType(targetType);
JsonDeserializer<?> deserializer = ctxt.findRootValueDeserializer(HymansonType);
JsonParser nodeParser = root.traverse(ctxt.getParser().getCodec());
nodeParser.nextToken();
return (MyInterface) deserializer.deserialize(nodeParser, ctxt);
}
There are a bunch of improvements to make to this custom deserializer, especially regarding tracking the context of the deserialization etc., but this should provide the functionality you're asking for.
这个自定义反序列化器有很多改进,特别是在跟踪反序列化的上下文等方面,但这应该提供您要求的功能。
回答by lcnicolau
In order to use your own ObjectMapper
inside a custom deserializer, you can use Hymanson Mix-in Annotations(theDefaultJsonDeserializer
interface) to dynamically remove the custom deserializer from the POJO
classes, avoiding the StackOverflowError
that would otherwise be thrown as a result of objectMapper.readValue(JsonParser, Class<T>)
.
为了使用自己ObjectMapper
定制的解串器里面,您可以使用Hyman逊混合式注解(该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
}
}
回答by Julio
This did the trick for me:
这对我有用:
ctxt.readValue(node, MyFailure.class)