3

I'm trying to write a null-safe List adapter that will serialize a nullable list to a non nullable object. I know you can do something like this:

object {
   @FromJson
   fun fromJson(@Nullable list: List<MyObject>?): List<MyObject> {
                return list ?: emptyList()
   }

    @ToJson
    fun toJson(@Nullable list: List<MyObject>?) = list ?: emptyList()

That works for a List<MyObject> but if I use List<Any> or List<T> it doesn't work. Is there any way to make it work for all lists?

Nathan
  • 33
  • 3

1 Answers1

1

The @FromJson/@ToJson adapters don't yet support generics like List. They match directly on the type. You will need a fully written out JsonAdapter.Factory. Remember to add the NullToEmptyListJsonAdapter.FACTORY to your Moshi.Builder.

final class NullToEmptyListJsonAdapter extends JsonAdapter<List<?>> {
  static final Factory FACTORY = new Factory() {
    @Nullable @Override
    public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
      if (!annotations.isEmpty()) {
        return null;
      }
      if (Types.getRawType(type) != List.class) {
        return null;
      }
      JsonAdapter<List<?>> objectJsonAdapter = moshi.nextAdapter(this, type, annotations);
      return new NullToEmptyListJsonAdapter(objectJsonAdapter);
    }
  };

  final JsonAdapter<List<?>> delegate;

  NullToEmptyListJsonAdapter(JsonAdapter<List<?>> delegate) {
    this.delegate = delegate;
  }

  @Override public List<?> fromJson(JsonReader reader) throws IOException {
    if (reader.peek() == JsonReader.Token.NULL) {
      reader.skipValue();
      return emptyList();
    }
    return delegate.fromJson(reader);
  }

  @Override public void toJson(JsonWriter writer, @Nullable List<?> value) throws IOException {
    if (value == null) {
      throw new IllegalStateException("Wrap JsonAdapter with .nullSafe().");
    }
    delegate.toJson(writer, value);
  }
}
Eric Cochran
  • 8,414
  • 5
  • 50
  • 91