2015-01-03 82 views
1

我測試RuntimeTypeAdapterFactoryTest:GSON RuntimeTypeAdapterFactory - 空項目序列化導致空指針異常

https://code.google.com/p/google-gson/source/browse/trunk/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java

這在最初的例子測試用例效果很好(testRuntimeTypeAdapter()):

https://code.google.com/p/google-gson/source/browse/trunk/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java#27

但是,如果一個註冊類型爲空,我會在RuntimeTypeAdapterFactory中得到一個NPE異常。擴展上面的原始示例:

static class Wallet { 
    BillingInstrument payment; 
} 

Wallet wallet = new Wallet(); 
// wallet.payment = new Card("Jo", 123); // leave wallet.payment uninitialized. 

gson.toJson(wallet); // throws NPE 

如果我初始化wallet.payment,則序列化工作正常。這裏的堆棧跟蹤:

Exception in thread, java.lang.NullPointerException 
at com.me.test.RuntimeTypeAdapterFactory$1.write(RuntimeTypeAdapterFactory.java:218) 
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:91) 
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:206) 
at com.google.gson.Gson.toJson(Gson.java:595) 
... 

這裏哪點:

https://code.google.com/p/google-gson/source/browse/trunk/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#218

有沒有人遇到這個,發現一個解決辦法? Gson應該默認情況下忽略序列化null值,所以不知道爲什麼它試圖序列化我的例子中的wallet.payment。

謝謝

回答

0

跑到同一個問題。 此修復程序爲我工作:

(RuntimeTypeAdapterFactory.java)

  @Override public void write(JsonWriter out, R value) throws IOException { 
      if(value!=null) { 
       Class<?> srcType = value.getClass(); 
       String label = subtypeToLabel.get(srcType); 
       @SuppressWarnings("unchecked") // registration requires that subtype extends T 
         TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType); 
       if (delegate == null) { 
        throw new JsonParseException("cannot serialize " + srcType.getName() 
          + "; did you forget to register a subtype?"); 
       } 
       JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject(); 
       if (jsonObject.has(typeFieldName)) { 
        throw new JsonParseException("cannot serialize " + srcType.getName() 
          + " because it already defines a field named " + typeFieldName); 
       } 
       JsonObject clone = new JsonObject(); 
       clone.add(typeFieldName, new JsonPrimitive(label)); 
       for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) { 
        clone.add(e.getKey(), e.getValue()); 
       } 
       Streams.write(clone, out); 
      }else{ 
       out.nullValue(); 
      }