【问题标题】:Gson RuntimeTypeAdapterFactory - null item to serialize leads to null pointer exceptionGson RuntimeTypeAdapterFactory - 要序列化的空项导致空指针异常
【发布时间】:2015-01-03 21:57:41
【问题描述】:

我正在测试 RuntimeTypeAdapterFactoryTest:

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

但如果注册类型为 null,我会在 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。

谢谢

【问题讨论】:

    标签: serialization gson


    【解决方案1】:

    这已在 2.4 版之前发生的 this commit 中修复

    【讨论】:

      【解决方案2】:

      遇到了同样的问题。 这个修复对我有用:

      (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();
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-02
        • 1970-01-01
        • 1970-01-01
        • 2014-08-02
        • 2015-09-12
        • 1970-01-01
        • 1970-01-01
        • 2015-09-03
        相关资源
        最近更新 更多