issue#2436: Throw exception when registering adapter for Object or JsonElement (#2479)
* Code changes and tests for #2436 to throw exception when trying to register adapter for Object or JsonElement * #2436 - Updates to User guide & comments to indicate exception cases and fix for 7 test cases of Parameterized Type * #2436 - Fixes as per the review comments. * #2436 - Refactored as per latest review comments + throwing error message. * #2436 - added a clarifying comment in a positive test case. * #2436 - formatting and minor changes as per review. * Update gson/src/main/java/com/google/gson/GsonBuilder.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/test/java/com/google/gson/GsonBuilderTest.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> * Update gson/src/test/java/com/google/gson/GsonBuilderTest.java Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com> --------- Co-authored-by: Sachin Patil <sachin.patil2@capitalone.com> Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
This commit is contained in:
parent
4dfae77af3
commit
0109f45129
|
@ -405,7 +405,9 @@ gson.registerTypeAdapter(MyType.class, new MyDeserializer());
|
|||
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
|
||||
```
|
||||
|
||||
`registerTypeAdapter` call checks if the type adapter implements more than one of these interfaces and register it for all of them.
|
||||
`registerTypeAdapter` call checks
|
||||
1. if the type adapter implements more than one of these interfaces, in that case it registers the adapter for all of them.
|
||||
2. if the type adapter is for the Object class or JsonElement or any of its subclasses, in that case it throws IllegalArgumentException because overriding the built-in adapters for these types is not supported.
|
||||
|
||||
#### Writing a Serializer
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.google.gson.internal.sql.SqlTypesSupport;
|
|||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayDeque;
|
||||
|
@ -664,6 +665,7 @@ public final class GsonBuilder {
|
|||
* @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
|
||||
* {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @throws IllegalArgumentException if the type adapter being registered is for {@code Object} class or {@link JsonElement} or any of its subclasses
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
|
||||
|
@ -672,6 +674,11 @@ public final class GsonBuilder {
|
|||
|| typeAdapter instanceof JsonDeserializer<?>
|
||||
|| typeAdapter instanceof InstanceCreator<?>
|
||||
|| typeAdapter instanceof TypeAdapter<?>);
|
||||
|
||||
if (isTypeObjectOrJsonElement(type)){
|
||||
throw new IllegalArgumentException("Cannot override built-in adapter for " + type);
|
||||
}
|
||||
|
||||
if (typeAdapter instanceof InstanceCreator<?>) {
|
||||
instanceCreators.put(type, (InstanceCreator<?>) typeAdapter);
|
||||
}
|
||||
|
@ -687,6 +694,12 @@ public final class GsonBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
private boolean isTypeObjectOrJsonElement(Type type) {
|
||||
return type instanceof Class &&
|
||||
(type == Object.class
|
||||
|| JsonElement.class.isAssignableFrom((Class<?>) type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a factory for type adapters. Registering a factory is useful when the type
|
||||
* adapter needs to be configured based on the type of the field being processed. Gson
|
||||
|
@ -718,6 +731,7 @@ public final class GsonBuilder {
|
|||
* @param typeAdapter This object must implement at least one of {@link TypeAdapter},
|
||||
* {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @throws IllegalArgumentException if the type adapter being registered is for {@link JsonElement} or any of its subclasses
|
||||
* @since 1.7
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
|
@ -726,6 +740,11 @@ public final class GsonBuilder {
|
|||
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|
||||
|| typeAdapter instanceof JsonDeserializer<?>
|
||||
|| typeAdapter instanceof TypeAdapter<?>);
|
||||
|
||||
if (JsonElement.class.isAssignableFrom(baseType)) {
|
||||
throw new IllegalArgumentException("Cannot override built-in adapter for " + baseType);
|
||||
}
|
||||
|
||||
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
|
||||
hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.google.gson;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
@ -254,4 +255,39 @@ public class GsonBuilderTest {
|
|||
assertThat(gson.newJsonReader(new StringReader("{}")).getStrictness()).isEqualTo(STRICTNESS);
|
||||
assertThat(gson.newJsonWriter(new StringWriter()).getStrictness()).isEqualTo(STRICTNESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterTypeAdapterForObjectAndJsonElements() {
|
||||
final String ERROR_MESSAGE = "Cannot override built-in adapter for ";
|
||||
Type[] types = {
|
||||
Object.class,
|
||||
JsonElement.class,
|
||||
JsonArray.class,
|
||||
};
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
for (Type type : types) {
|
||||
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
|
||||
() -> gsonBuilder.registerTypeAdapter(type, NULL_TYPE_ADAPTER));
|
||||
assertThat(e).hasMessageThat().isEqualTo(ERROR_MESSAGE + type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRegisterTypeHierarchyAdapterJsonElements() {
|
||||
final String ERROR_MESSAGE = "Cannot override built-in adapter for ";
|
||||
Class<?>[] types = {
|
||||
JsonElement.class,
|
||||
JsonArray.class,
|
||||
};
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
for (Class<?> type : types) {
|
||||
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
|
||||
() -> gsonBuilder.registerTypeHierarchyAdapter(type, NULL_TYPE_ADAPTER));
|
||||
|
||||
assertThat(e).hasMessageThat().isEqualTo(ERROR_MESSAGE + type);
|
||||
}
|
||||
// But registering type hierarchy adapter for Object should be allowed
|
||||
gsonBuilder.registerTypeHierarchyAdapter(Object.class, NULL_TYPE_ADAPTER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ public final class GsonTest {
|
|||
Collections.<ReflectionAccessFilter>emptyList());
|
||||
|
||||
Gson clone = original.newBuilder()
|
||||
.registerTypeAdapter(Object.class, new TestTypeAdapter())
|
||||
.registerTypeAdapter(int.class, new TestTypeAdapter())
|
||||
.create();
|
||||
|
||||
assertThat(clone.factories).hasSize(original.factories.size() + 1);
|
||||
|
|
Loading…
Reference in New Issue
Block a user