gpt4 book ai didi

java - jackson 2.2.x : recursive deserialization fails, 为什么?

转载 作者:太空宇宙 更新时间:2023-11-04 14:25:48 25 4
gpt4 key购买 nike

准确地说,这是 Jackson 2.2.3。

反序列化过程非常复杂,因为根据我反序列化的 JSON 值的类型,类会发生变化:

  • 基本抽象类是JsonMergePatch
  • 当 JSON 值不是 JSON 对象时,我会反序列化为 NonObjectMergePatch
  • 否则,我会递归反序列化为 ObjectMergePatch

这是代码(为了“简洁”,省略了导入);首先是 JsonMergePatch:

@JsonDeserialize(using = JsonMergePatchDeserializer.class)
public abstract class JsonMergePatch
implements JsonSerializable
{
public abstract JsonNode apply(final JsonNode input)
throws JsonPatchException;
}

NonObjectMergePatch:

final class NonObjectMergePatch
extends JsonMergePatch
{
private final JsonNode node;

NonObjectMergePatch(@Nonnull final JsonNode node)
{
this.node = Preconditions.checkNotNull(node);
}

@Override
public JsonNode apply(final JsonNode input)
throws JsonPatchException
{
return null; // TODO!
}

@Override
public void serialize(final JsonGenerator jgen,
final SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeTree(node);
}

@Override
public void serializeWithType(final JsonGenerator jgen,
final SerializerProvider provider, final TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
serialize(jgen, provider);
}
}

ObjectMergePatch:

final class ObjectMergePatch
extends JsonMergePatch
{
private final Set<String> removedMembers;
private final Map<String, JsonMergePatch> modifiedMembers;

ObjectMergePatch(final Set<String> removedMembers,
final Map<String, JsonMergePatch> modifiedMembers)
{
this.removedMembers = ImmutableSet.copyOf(removedMembers);
this.modifiedMembers = ImmutableMap.copyOf(modifiedMembers);
}

@Override
public JsonNode apply(final JsonNode input)
throws JsonPatchException
{
return null;
}

@Override
public void serialize(final JsonGenerator jgen,
final SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeStartObject();

/*
* Write removed members as JSON nulls
*/
for (final String member: removedMembers)
jgen.writeNullField(member);

/*
* Write modified members; delegate to serialization for writing values
*/
for (final Map.Entry<String, JsonMergePatch> entry:
modifiedMembers.entrySet()) {
jgen.writeFieldName(entry.getKey());
entry.getValue().serialize(jgen, provider);
}

jgen.writeEndObject();
}

@Override
public void serializeWithType(final JsonGenerator jgen,
final SerializerProvider provider, final TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
serialize(jgen, provider);
}
}

最后,自定义反序列化器:

final class JsonMergePatchDeserializer
extends JsonDeserializer<JsonMergePatch>
{
@Override
public JsonMergePatch deserialize(final JsonParser jp,
final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
/* FAILS HERE */
final JsonNode node = jp.readValueAsTree();
/*
* Not an object: the simple case
*/
if (!node.isObject())
return new NonObjectMergePatch(node);

/*
* The complicated case...
*
* We have to build a set of removed members, plus a map of modified
* members.
*/

final Set<String> removedMembers = Sets.newHashSet();
final Map<String, JsonMergePatch> modifiedMembers = Maps.newHashMap();
final Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();

Map.Entry<String, JsonNode> entry;

while (iterator.hasNext()) {
entry = iterator.next();
if (entry.getValue().isNull())
removedMembers.add(entry.getKey());
else {
final JsonMergePatch value
= deserialize(entry.getValue().traverse(), ctxt);
modifiedMembers.put(entry.getKey(), value);
}
}

return new ObjectMergePatch(removedMembers, modifiedMembers);
}

/*
* This method MUST be overriden... The default is to return null, which is
* not what we want.
*/
@Override
public JsonMergePatch getNullValue()
{
return new NonObjectMergePatch(NullNode.getInstance());
}
}

我已经编写了测试代码,只要要反序列化的 JSON 不是对象,该测试就可以正常工作;当它是一个对象时,我递归地调用 deserialize() 方法来反序列化对象成员值...但是从解析器读取值失败(标记为 /* FAILS HERE */上面),但有一个异常(exception):

java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree
at com.fasterxml.jackson.core.JsonParser.readValueAsTree(JsonParser.java:1352)
at com.github.fge.jsonpatch.rfc7386.JsonMergePatchDeserializer.deserialize(JsonMergePatchDeserializer.java:67)
at com.github.fge.jsonpatch.rfc7386.JsonMergePatchDeserializer.deserialize(JsonMergePatchDeserializer.java:92)
at com.github.fge.jsonpatch.rfc7386.JsonMergePatchDeserializer.deserialize(JsonMergePatchDeserializer.java:36)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
at com.github.fge.jsonpatch.rfc7386.SerializationTest.objectSerDeserWorksCorrectly(SerializationTest.java:102)
为什么?我该如何解决这个问题?

最佳答案

嗯,在谷歌搜索时,我偶然发现了 a previous question of mine并给出了答案;但我说它很丑......

正如异常提到的,问题是 JsonParser 实例没有关联的 ObjectCodec。所以,我们必须喂它一个;这里的问题是为什么这不会自动完成......

因此,在自定义反序列化器中,我声明了一个新的 ObjectCodec,如下所示:

// JacksonUtils is a class of mine; the method returns an ObjectMapper,
// which extends ObjectCodec
private static final ObjectCodec CODEC = JacksonUtils.newMapper();

.deserialize() 方法中,我这样做:

jp.setCodec(CODEC);

并且它有效。

但是很丑。太糟糕了。它是可怕的。我想要一个更好的解决方案:/

关于java - jackson 2.2.x : recursive deserialization fails, 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26675461/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com