정확히 말하면 Jackson 2.2.3입니다.Jackson 2.2.x : 재귀 적 직렬화가 실패합니다. 이유가 무엇입니까?
역 직렬화 프로세스가 내가 역 직렬화 json으로 값, 클래스 변경의 종류에 따라하기 때문에 매우 복잡하다 :
- 기본은, 추상 클래스는
JsonMergePatch
이다; - JSON 값이 JSON 객체가 아닌 경우, 나는
NonObjectMergePatch
으로 비 직렬화됩니다. - 그렇지 않으면 재귀 적으로 역 직렬화하여
ObjectMergePatch
이됩니다.@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); } }
마지막
JsonMergePatch
우선 여기서
코드 (수입 간략화 "생략) 인 , 주문 deserial izer :
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이 객체가 아닌 한 제대로 작동하는 테스트를 코딩했습니다. 그것이 객체이면, I 재귀이 예외 (상기 /* FAILS HERE */
표시)가 실패 대상 부재 값을 역 직렬화하는 deserialize()
메소드를 호출하지만 ... 파서로부터 값을 판독 :
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)
왜? 이 문제를 어떻게 해결할 수 있습니까?
추악 할 것이므로 이것은 필수적이지 않아야한다. 데이터 바인딩 코드는 버퍼 토큰을위한 임시 파서를 생성해야하는 경우'codec' 인스턴스를 전파해야합니다. 어딘가에 버그처럼 들립니다. 반대로 사용자 정의 디시리얼라이저가 버퍼링을 사용하면'TokenBuffer '에'JsonParser'를 전달해야합니다. – StaxMan
흠, 그래서 2.2.3을 사용합니다. 나는 2.2.4를 아직 사용하지 않았다. – fge
아. 잘 될 수도 있습니다 - 비슷한 문제가 그 이후로 수정되었습니다. 가능한 경우 및 필요한 경우 최대 2.4.3을 사용하려고합니다.문제가 지속되면 최신 버전이 수정되었는지 확인하십시오). 2.4.3에는 내가 생각할 수있는 모든 관련 픽스가있다. – StaxMan