Как предотвратить использование NPE при отсутствии атрибута JSON при использовании Gson + AutoValueGson? - PullRequest
0 голосов
/ 20 апреля 2020

Вокруг этой проблемы много похожих вопросов, но ни один из них не дал решения, которое, кажется, работает для следующего варианта использования. Я хотел бы десериализовать JSON в объект AutoValue, где у JSON отсутствует атрибут. Я хочу использовать Optional API и для отсутствующего атрибута получить Optional.empty(). См. Ниже

Foo. java

@AutoValue
public abstract class Foo {

  public abstract Optional<String> bar();

  public abstract Optional<String> version();


  public static Builder builder() {
    return new AutoValue_Foo.Builder();
  }

  public static TypeAdapter<Foo> typeAdapter(Gson gson) {
    return new AutoValue_Foo.GsonTypeAdapter(gson).nullSafe();
  }

  @AutoValue.Builder
  public abstract static class Builder {

    public abstract Builder bar(String bar);

    public abstract Builder version(String version);

    public abstract Foo build();
  }
}

AutoValueGsonAdapterFactory. java

/**
 * A factory to prevent adding each generated {@link TypeAdapter} to {@link Gson} instance manually
 *
 * <p>See https://github.com/rharter/auto-value-gson
 */
@GsonTypeAdapterFactory
public abstract class AutoValueGsonAdapterFactory implements TypeAdapterFactory {

  // Static factory method to access the package
  // private generated implementation
  public static TypeAdapterFactory create() {
    return new AutoValueGson_AutoValueGsonAdapterFactory();
  }
}

Метод тестирования

  @Test
  public void testDeserialization() throws IOException {
    Gson gson = getGson();
    Path jsonFilePath = Utils.readResourcePath(getClass(), "sample-foo-with-missing-attribute.json");
    String json = Utils.read(jsonFilePath);

    Foo foo = gson.fromJson(json, Foo.class);

    assertTrue(foo.version().isPresent());
  }

  private Gson getGson() {
    return new GsonBuilder()
        .registerTypeAdapterFactory(AutoValueGsonAdapterFactory.create())
        .create();
  }

sample-foo-with-missing-attribute. json

{
   "version": {
     "value": "1.0"
   }
}

При запуске метода тестирования выше вывод:

FAILURE com.sample.test-autovalue-gson.model.Metadata2Test testDeserialization: Null bar
java.lang.NullPointerException: Null bar
    at com.sample.test-autovalue-gson.model.$AutoValue_Foo.<init>($AutoValue_Foo.java:19)
    at com.sample.test-autovalue-gson.model.AutoValue_Foo.<init>(AutoValue_Foo.java:22)
    at com.sample.test-autovalue-gson.model.AutoValue_Foo$GsonTypeAdapter.read(AutoValue_Foo.java:100)
    at com.sample.test-autovalue-gson.model.AutoValue_Foo$GsonTypeAdapter.read(AutoValue_Foo.java:25)
    at com.google.gson.Gson.fromJson(Gson.java:888)
    at com.google.gson.Gson.fromJson(Gson.java:853)
    at com.google.gson.Gson.fromJson(Gson.java:802)
    at com.google.gson.Gson.fromJson(Gson.java:774)

Lib версии

  • авто-аннотации значения 1.6.3
  • авто-значение аннотации 0,8,0
  • Гсон 2,8,2
...