Fixed nullSafe usage. (#1555)
The JsonSerializer/Deserializer adapters used to ignore this attribute which result in inconsistent behaviour for annotated adapters. Fixes #1553 Signed-off-by: Dmitry Bufistov <dmitry@midokura.com> Co-authored-by: Dmitry Bufistov <dmitry@midokura.com>
This commit is contained in:
parent
98f2bbf4c1
commit
46b97bf156
@ -55,6 +55,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte
|
|||||||
Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct();
|
Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct();
|
||||||
|
|
||||||
TypeAdapter<?> typeAdapter;
|
TypeAdapter<?> typeAdapter;
|
||||||
|
boolean nullSafe = annotation.nullSafe();
|
||||||
if (instance instanceof TypeAdapter) {
|
if (instance instanceof TypeAdapter) {
|
||||||
typeAdapter = (TypeAdapter<?>) instance;
|
typeAdapter = (TypeAdapter<?>) instance;
|
||||||
} else if (instance instanceof TypeAdapterFactory) {
|
} else if (instance instanceof TypeAdapterFactory) {
|
||||||
@ -66,7 +67,8 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte
|
|||||||
JsonDeserializer<?> deserializer = instance instanceof JsonDeserializer
|
JsonDeserializer<?> deserializer = instance instanceof JsonDeserializer
|
||||||
? (JsonDeserializer) instance
|
? (JsonDeserializer) instance
|
||||||
: null;
|
: null;
|
||||||
typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null);
|
typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null, nullSafe);
|
||||||
|
nullSafe = false;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Invalid attempt to bind an instance of "
|
throw new IllegalArgumentException("Invalid attempt to bind an instance of "
|
||||||
+ instance.getClass().getName() + " as a @JsonAdapter for " + type.toString()
|
+ instance.getClass().getName() + " as a @JsonAdapter for " + type.toString()
|
||||||
@ -74,7 +76,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte
|
|||||||
+ " JsonSerializer or JsonDeserializer.");
|
+ " JsonSerializer or JsonDeserializer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeAdapter != null && annotation.nullSafe()) {
|
if (typeAdapter != null && nullSafe) {
|
||||||
typeAdapter = typeAdapter.nullSafe();
|
typeAdapter = typeAdapter.nullSafe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,17 +45,24 @@ public final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
|||||||
private final TypeToken<T> typeToken;
|
private final TypeToken<T> typeToken;
|
||||||
private final TypeAdapterFactory skipPast;
|
private final TypeAdapterFactory skipPast;
|
||||||
private final GsonContextImpl context = new GsonContextImpl();
|
private final GsonContextImpl context = new GsonContextImpl();
|
||||||
|
private final boolean nullSafe;
|
||||||
|
|
||||||
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
||||||
private volatile TypeAdapter<T> delegate;
|
private volatile TypeAdapter<T> delegate;
|
||||||
|
|
||||||
public TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
|
public TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
|
||||||
Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
|
Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast, boolean nullSafe) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
this.deserializer = deserializer;
|
this.deserializer = deserializer;
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
this.typeToken = typeToken;
|
this.typeToken = typeToken;
|
||||||
this.skipPast = skipPast;
|
this.skipPast = skipPast;
|
||||||
|
this.nullSafe = nullSafe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
|
||||||
|
Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
|
||||||
|
this(serializer, deserializer, gson, typeToken, skipPast, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public T read(JsonReader in) throws IOException {
|
@Override public T read(JsonReader in) throws IOException {
|
||||||
@ -63,7 +70,7 @@ public final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
|||||||
return delegate().read(in);
|
return delegate().read(in);
|
||||||
}
|
}
|
||||||
JsonElement value = Streams.parse(in);
|
JsonElement value = Streams.parse(in);
|
||||||
if (value.isJsonNull()) {
|
if (nullSafe && value.isJsonNull()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return deserializer.deserialize(value, typeToken.getType(), context);
|
return deserializer.deserialize(value, typeToken.getType(), context);
|
||||||
@ -74,7 +81,7 @@ public final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
|||||||
delegate().write(out, value);
|
delegate().write(out, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null) {
|
if (nullSafe && value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -161,4 +161,22 @@ public final class JsonAdapterSerializerDeserializerTest extends TestCase {
|
|||||||
return new JsonPrimitive("BaseIntegerAdapter");
|
return new JsonPrimitive("BaseIntegerAdapter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testJsonAdapterNullSafe() {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String json = gson.toJson(new Computer3(null, null));
|
||||||
|
assertEquals("{\"user1\":\"UserSerializerDeserializer\"}", json);
|
||||||
|
Computer3 computer3 = gson.fromJson("{\"user1\":null, \"user2\":null}", Computer3.class);
|
||||||
|
assertEquals("UserSerializerDeserializer", computer3.user1.name);
|
||||||
|
assertNull(computer3.user2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Computer3 {
|
||||||
|
@JsonAdapter(value = UserSerializerDeserializer.class, nullSafe = false) final User user1;
|
||||||
|
@JsonAdapter(value = UserSerializerDeserializer.class) final User user2;
|
||||||
|
Computer3(User user1, User user2) {
|
||||||
|
this.user1 = user1;
|
||||||
|
this.user2 = user2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user