Skip to content

Commit 0201ff7

Browse files
sachinp97Sachin PatilMarcono1234
authored andcommitted
issue#2436: Throw exception when registering adapter for Object or JsonElement (google#2479)
* Code changes and tests for google#2436 to throw exception when trying to register adapter for Object or JsonElement * google#2436 - Updates to User guide & comments to indicate exception cases and fix for 7 test cases of Parameterized Type * google#2436 - Fixes as per the review comments. * google#2436 - Refactored as per latest review comments + throwing error message. * google#2436 - added a clarifying comment in a positive test case. * google#2436 - formatting and minor changes as per review. * Update gson/src/main/java/com/google/gson/GsonBuilder.java Co-authored-by: Marcono1234 <[email protected]> * Update gson/src/test/java/com/google/gson/GsonBuilderTest.java Co-authored-by: Marcono1234 <[email protected]> * Update gson/src/test/java/com/google/gson/GsonBuilderTest.java Co-authored-by: Marcono1234 <[email protected]> --------- Co-authored-by: Sachin Patil <[email protected]> Co-authored-by: Marcono1234 <[email protected]>
1 parent c5a1568 commit 0201ff7

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

UserGuide.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,9 @@ gson.registerTypeAdapter(MyType.class, new MyDeserializer());
405405
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
406406
```
407407

408-
`registerTypeAdapter` call checks if the type adapter implements more than one of these interfaces and register it for all of them.
408+
`registerTypeAdapter` call checks
409+
1. if the type adapter implements more than one of these interfaces, in that case it registers the adapter for all of them.
410+
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.
409411

410412
#### Writing a Serializer
411413

gson/src/main/java/com/google/gson/GsonBuilder.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.google.gson.reflect.TypeToken;
4242
import com.google.gson.stream.JsonReader;
4343
import com.google.gson.stream.JsonWriter;
44+
import java.lang.reflect.ParameterizedType;
4445
import java.lang.reflect.Type;
4546
import java.text.DateFormat;
4647
import java.util.ArrayDeque;
@@ -664,6 +665,7 @@ public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
664665
* @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
665666
* {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
666667
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
668+
* @throws IllegalArgumentException if the type adapter being registered is for {@code Object} class or {@link JsonElement} or any of its subclasses
667669
*/
668670
@CanIgnoreReturnValue
669671
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
@@ -672,6 +674,11 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
672674
|| typeAdapter instanceof JsonDeserializer<?>
673675
|| typeAdapter instanceof InstanceCreator<?>
674676
|| typeAdapter instanceof TypeAdapter<?>);
677+
678+
if (isTypeObjectOrJsonElement(type)){
679+
throw new IllegalArgumentException("Cannot override built-in adapter for " + type);
680+
}
681+
675682
if (typeAdapter instanceof InstanceCreator<?>) {
676683
instanceCreators.put(type, (InstanceCreator<?>) typeAdapter);
677684
}
@@ -687,6 +694,12 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
687694
return this;
688695
}
689696

697+
private boolean isTypeObjectOrJsonElement(Type type) {
698+
return type instanceof Class &&
699+
(type == Object.class
700+
|| JsonElement.class.isAssignableFrom((Class<?>) type));
701+
}
702+
690703
/**
691704
* Register a factory for type adapters. Registering a factory is useful when the type
692705
* adapter needs to be configured based on the type of the field being processed. Gson
@@ -718,6 +731,7 @@ public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
718731
* @param typeAdapter This object must implement at least one of {@link TypeAdapter},
719732
* {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
720733
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
734+
* @throws IllegalArgumentException if the type adapter being registered is for {@link JsonElement} or any of its subclasses
721735
* @since 1.7
722736
*/
723737
@CanIgnoreReturnValue
@@ -726,6 +740,11 @@ public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAd
726740
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
727741
|| typeAdapter instanceof JsonDeserializer<?>
728742
|| typeAdapter instanceof TypeAdapter<?>);
743+
744+
if (JsonElement.class.isAssignableFrom(baseType)) {
745+
throw new IllegalArgumentException("Cannot override built-in adapter for " + baseType);
746+
}
747+
729748
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
730749
hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
731750
}

gson/src/test/java/com/google/gson/GsonBuilderTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.gson;
1818

1919
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.assertThrows;
2021
import static org.junit.Assert.fail;
2122

2223
import com.google.gson.stream.JsonReader;
@@ -254,4 +255,39 @@ public void testSetStrictness() throws IOException {
254255
assertThat(gson.newJsonReader(new StringReader("{}")).getStrictness()).isEqualTo(STRICTNESS);
255256
assertThat(gson.newJsonWriter(new StringWriter()).getStrictness()).isEqualTo(STRICTNESS);
256257
}
258+
259+
@Test
260+
public void testRegisterTypeAdapterForObjectAndJsonElements() {
261+
final String ERROR_MESSAGE = "Cannot override built-in adapter for ";
262+
Type[] types = {
263+
Object.class,
264+
JsonElement.class,
265+
JsonArray.class,
266+
};
267+
GsonBuilder gsonBuilder = new GsonBuilder();
268+
for (Type type : types) {
269+
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
270+
() -> gsonBuilder.registerTypeAdapter(type, NULL_TYPE_ADAPTER));
271+
assertThat(e).hasMessageThat().isEqualTo(ERROR_MESSAGE + type);
272+
}
273+
}
274+
275+
276+
@Test
277+
public void testRegisterTypeHierarchyAdapterJsonElements() {
278+
final String ERROR_MESSAGE = "Cannot override built-in adapter for ";
279+
Class<?>[] types = {
280+
JsonElement.class,
281+
JsonArray.class,
282+
};
283+
GsonBuilder gsonBuilder = new GsonBuilder();
284+
for (Class<?> type : types) {
285+
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
286+
() -> gsonBuilder.registerTypeHierarchyAdapter(type, NULL_TYPE_ADAPTER));
287+
288+
assertThat(e).hasMessageThat().isEqualTo(ERROR_MESSAGE + type);
289+
}
290+
// But registering type hierarchy adapter for Object should be allowed
291+
gsonBuilder.registerTypeHierarchyAdapter(Object.class, NULL_TYPE_ADAPTER);
292+
}
257293
}

gson/src/test/java/com/google/gson/GsonTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void testClonedTypeAdapterFactoryListsAreIndependent() {
9393
Collections.<ReflectionAccessFilter>emptyList());
9494

9595
Gson clone = original.newBuilder()
96-
.registerTypeAdapter(Object.class, new TestTypeAdapter())
96+
.registerTypeAdapter(int.class, new TestTypeAdapter())
9797
.create();
9898

9999
assertThat(clone.factories).hasSize(original.factories.size() + 1);

0 commit comments

Comments
 (0)