Адаптеры типа, самое сердце сериализации / десериализации Gson, могут помочь практически во всех случаях.
Все, что вам нужно, это просто реализовать один.
final class CollectionFalseAsNullTypeAdapterFactory
implements TypeAdapterFactory {
private static final TypeAdapterFactory instance = new CollectionFalseAsNullTypeAdapterFactory();
private CollectionFalseAsNullTypeAdapterFactory() {
}
static TypeAdapterFactory get() {
return instance;
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if ( !Collection.class.isAssignableFrom(typeToken.getRawType()) ) {
return null;
}
@SuppressWarnings("unchecked")
final TypeAdapter<Collection<Object>> delegateTypeAdapter = (TypeAdapter<Collection<Object>>) gson.getDelegateAdapter(this, typeToken);
@SuppressWarnings("unchecked")
final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) new CollectionFalseAsNullTypeAdapter<>(delegateTypeAdapter);
return typeAdapter;
}
private static final class CollectionFalseAsNullTypeAdapter<E>
extends TypeAdapter<Collection<E>> {
private final TypeAdapter<Collection<E>> delegateTypeAdapter;
private CollectionFalseAsNullTypeAdapter(final TypeAdapter<Collection<E>> delegateTypeAdapter) {
this.delegateTypeAdapter = delegateTypeAdapter;
}
@Override
public void write(final JsonWriter out, final Collection<E> value)
throws IOException {
delegateTypeAdapter.write(out, value);
}
@Override
public Collection<E> read(final JsonReader in)
throws IOException {
// Let's just make sure it's a boolean
if ( in.peek() == JsonToken.BOOLEAN ) {
// If yes, then just return a null skipping the boolean
in.skipValue();
return null;
}
return delegateTypeAdapter.read(in);
}
}
}
Пример использования:
private static final Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.registerTypeAdapterFactory(CollectionFalseAsNullTypeAdapterFactory.get())
.create();
public static void main(final String... args)
throws IOException {
for ( final String resourceName : ImmutableList.of("non-null.json", "null.json") ) {
try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q50013856.class, resourceName) ) {
final Entity entity = gson.fromJson(jsonReader, Entity.class);
System.out.println(entity);
}
}
}
Пример вывода (при условии, что toString
переопределено):
Entity {tags = [Tag {contentId = 13, tagId = 3, создан = понедельник, 26 марта 11:09:08 EEST 2018, tagName = FICTION}, Tag {contentId = 13, tagId = 7, создан = понедельник 26 11:09:08 EEST 2018, tagName = ФУНКЦИЯ ЮВЕНИЛЯ}]}
Entity {tags = null}
Обратите внимание, что вы можете аннотировать поле tags
, чтобы оно было более точным, чем глобальная регистрация завода:
@JsonAdapter(CollectionFalseAsNullTypeAdapterFactory.class)
final List<Tag> tags = null;