Skip to content

Commit a2b1c3c

Browse files
authored
Allow registering adapters for JsonElement again (#2789)
This is done for backward compatibility, however registering the adapter still has no effect because the built-in adapter as higher precedence (like it is the case for multiple years already). The Javadoc for the GsonBuilder methods has not been adjusted, to discourage users from trying to register adapters for JsonElement.
1 parent e5dce84 commit a2b1c3c

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

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

+9-8
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
710710
|| typeAdapter instanceof InstanceCreator<?>
711711
|| typeAdapter instanceof TypeAdapter<?>);
712712

713-
if (isTypeObjectOrJsonElement(type)) {
713+
if (hasNonOverridableAdapter(type)) {
714714
throw new IllegalArgumentException("Cannot override built-in adapter for " + type);
715715
}
716716

@@ -730,9 +730,14 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
730730
return this;
731731
}
732732

733-
private static boolean isTypeObjectOrJsonElement(Type type) {
734-
return type instanceof Class
735-
&& (type == Object.class || JsonElement.class.isAssignableFrom((Class<?>) type));
733+
/** Whether the type has a built-in adapter which cannot be overridden. */
734+
private static boolean hasNonOverridableAdapter(Type type) {
735+
return type == Object.class;
736+
// This should also cover `JsonElement.class.isAssignableFrom(type)`, however for backward
737+
// compatibility this is not covered here because really old Gson versions had no built-in
738+
// adapter for JsonElement so users registered custom adapters. These adapters don't have any
739+
// effect in recent Gson versions. See
740+
// https://github.com/google/gson/issues/2787#issuecomment-2581568157
736741
}
737742

738743
/**
@@ -778,10 +783,6 @@ public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAd
778783
|| typeAdapter instanceof JsonDeserializer<?>
779784
|| typeAdapter instanceof TypeAdapter<?>);
780785

781-
if (JsonElement.class.isAssignableFrom(baseType)) {
782-
throw new IllegalArgumentException("Cannot override built-in adapter for " + baseType);
783-
}
784-
785786
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
786787
hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
787788
}

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.lang.reflect.Type;
2929
import java.text.DateFormat;
3030
import java.util.Date;
31+
import org.junit.Ignore;
3132
import org.junit.Test;
3233

3334
/**
@@ -251,7 +252,10 @@ public void testSetStrictness() throws IOException {
251252
public void testRegisterTypeAdapterForObjectAndJsonElements() {
252253
String errorMessage = "Cannot override built-in adapter for ";
253254
Type[] types = {
254-
Object.class, JsonElement.class, JsonArray.class,
255+
Object.class,
256+
// TODO: Registering adapter for JsonElement is allowed (for now) for backward compatibility,
257+
// see https://github.com/google/gson/issues/2787
258+
// JsonElement.class, JsonArray.class,
255259
};
256260
GsonBuilder gsonBuilder = new GsonBuilder();
257261
for (Type type : types) {
@@ -263,6 +267,22 @@ public void testRegisterTypeAdapterForObjectAndJsonElements() {
263267
}
264268
}
265269

270+
/**
271+
* Verifies that (for now) registering adapter for {@link JsonElement} and subclasses is possible,
272+
* but has no effect. See {@link #testRegisterTypeAdapterForObjectAndJsonElements()}.
273+
*/
274+
@Test
275+
public void testRegisterTypeAdapterForJsonElements() {
276+
Gson gson = new GsonBuilder().registerTypeAdapter(JsonArray.class, NULL_TYPE_ADAPTER).create();
277+
TypeAdapter<JsonArray> adapter = gson.getAdapter(JsonArray.class);
278+
// Does not use registered adapter
279+
assertThat(adapter).isNotSameInstanceAs(NULL_TYPE_ADAPTER);
280+
assertThat(adapter.toJson(new JsonArray())).isEqualTo("[]");
281+
}
282+
283+
@Ignore(
284+
"Registering adapter for JsonElement is allowed (for now) for backward compatibility, see"
285+
+ " https://github.com/google/gson/issues/2787")
266286
@Test
267287
public void testRegisterTypeHierarchyAdapterJsonElements() {
268288
String errorMessage = "Cannot override built-in adapter for ";
@@ -282,6 +302,20 @@ public void testRegisterTypeHierarchyAdapterJsonElements() {
282302
gsonBuilder.registerTypeHierarchyAdapter(Object.class, NULL_TYPE_ADAPTER);
283303
}
284304

305+
/**
306+
* Verifies that (for now) registering hierarchy adapter for {@link JsonElement} and subclasses is
307+
* possible, but has no effect. See {@link #testRegisterTypeHierarchyAdapterJsonElements()}.
308+
*/
309+
@Test
310+
public void testRegisterTypeHierarchyAdapterJsonElements_Allowed() {
311+
Gson gson =
312+
new GsonBuilder().registerTypeHierarchyAdapter(JsonArray.class, NULL_TYPE_ADAPTER).create();
313+
TypeAdapter<JsonArray> adapter = gson.getAdapter(JsonArray.class);
314+
// Does not use registered adapter
315+
assertThat(adapter).isNotSameInstanceAs(NULL_TYPE_ADAPTER);
316+
assertThat(adapter.toJson(new JsonArray())).isEqualTo("[]");
317+
}
318+
285319
@Test
286320
public void testSetDateFormatWithInvalidPattern() {
287321
GsonBuilder builder = new GsonBuilder();

0 commit comments

Comments
 (0)