2014-10-31 49 views
1

準確地說,這是Jackson 2.2.3。Jackson 2.2.x:遞歸反序列化失敗,爲什麼?

的反序列化過程是相當複雜的,因爲這取決於JSON值I反序列化,類的變化的類型:

  • 基,抽象類是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); 
    } 
} 

最後,自定義的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不是一個對象;當它是一個對象,我遞歸調用的方法deserialize()反序列化對象的成員值......但閱讀從解析器值失敗與此異常(上面注/* FAILS HERE */):

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) 

爲什麼?我怎麼解決這個問題?

回答

0

唔,當用google搜索時,我偶然發現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); 

它的工作原理。

但它很醜。它很爛。它是可怕的。我想要一個更好的解決方案:/

+0

這應該沒有必要,因爲它會很醜。數據綁定代碼應該在需要爲緩衝令牌創建臨時解析器的情況下傳播'codec'實例;所以這聽起來像是一個錯誤的地方。相反,如果自定義反序列化器使用緩衝,則需要確保爲'TokenBuffer'傳遞'JsonParser'。 – StaxMan 2014-10-31 17:22:52

+0

嗯,所以我用2.2.3;我還沒有使用2.2.4,這會有所作爲嗎? – fge 2014-10-31 17:30:52

+0

啊。很可能 - 從那時起,類似的問題就得到解決。雖然我會嘗試使用高達2.4.3,如果可能和必要(即如果問題仍然存在,請嘗試查看後續版本是否修復)。 2.4.3有我能想到的所有相關修復。 – StaxMan 2014-10-31 17:34:43