Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/github_actions/github-actions-bb9…
Browse files Browse the repository at this point in the history
…d44e1db
  • Loading branch information
eamonnmcmanus authored Jan 29, 2025
2 parents cf1a470 + 10bdd6d commit 3c1635d
Show file tree
Hide file tree
Showing 19 changed files with 106 additions and 68 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ There are a few open-source projects that can convert Java objects to JSON. Howe
Gradle:
```gradle
dependencies {
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.google.code.gson:gson:2.12.0'
}
```

Expand All @@ -33,7 +33,7 @@ Maven:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.12.0</version>
</dependency>
```

Expand Down
4 changes: 2 additions & 2 deletions UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The Gson instance does not maintain any state while invoking JSON operations. So

```gradle
dependencies {
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.google.code.gson:gson:2.12.0'
}
```

Expand All @@ -90,7 +90,7 @@ To use Gson with Maven2/3, you can use the Gson version available in Maven Centr
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
<version>2.12.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand Down
4 changes: 2 additions & 2 deletions extras/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<parent>
<groupId>com.google.code.gson</groupId>
<artifactId>gson-parent</artifactId>
<version>2.11.1-SNAPSHOT</version>
<version>2.12.1-SNAPSHOT</version>
</parent>

<artifactId>gson-extras</artifactId>
Expand All @@ -30,7 +30,7 @@
<properties>
<!-- Make the build reproducible, see root `pom.xml` -->
<!-- This is duplicated here because that is recommended by `artifact:check-buildplan` -->
<project.build.outputTimestamp>2024-05-19T18:54:10Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2025-01-27T22:40:20Z</project.build.outputTimestamp>

<!-- Overwrite property from parent; this module is currently not deployed -->
<gson.isInternalModule>true</gson.isInternalModule>
Expand Down
12 changes: 6 additions & 6 deletions gson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.code.gson</groupId>
<artifactId>gson-parent</artifactId>
<version>2.11.1-SNAPSHOT</version>
<version>2.12.1-SNAPSHOT</version>
</parent>

<artifactId>gson</artifactId>
Expand All @@ -36,7 +36,7 @@
<properties>
<!-- Make the build reproducible, see root `pom.xml` -->
<!-- This is duplicated here because that is recommended by `artifact:check-buildplan` -->
<project.build.outputTimestamp>2024-05-19T18:54:10Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2025-01-27T22:40:20Z</project.build.outputTimestamp>

<excludeTestCompilation>**/Java17*</excludeTestCompilation>
</properties>
Expand Down Expand Up @@ -66,13 +66,13 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>33.3.1-jre</version>
<version>33.4.0-jre</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.3.1-jre</version>
<version>33.4.0-jre</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down Expand Up @@ -236,12 +236,12 @@
<dependency>
<groupId>com.guardsquare</groupId>
<artifactId>proguard-base</artifactId>
<version>7.6.0</version>
<version>7.6.1</version>
</dependency>
<dependency>
<groupId>com.guardsquare</groupId>
<artifactId>proguard-core</artifactId>
<version>9.1.6</version>
<version>9.1.7</version>
</dependency>
</dependencies>
<configuration>
Expand Down
17 changes: 9 additions & 8 deletions gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
|| typeAdapter instanceof InstanceCreator<?>
|| typeAdapter instanceof TypeAdapter<?>);

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

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

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

/**
Expand Down Expand Up @@ -778,10 +783,6 @@ public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAd
|| 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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {

Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
TypeAdapter<?> wrappedTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(gson, elementTypeAdapter, elementType);
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
TypeAdapter<T> result = new Adapter(wrappedTypeAdapter, constructor);
return result;
}

Expand All @@ -61,12 +63,8 @@ private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final ObjectConstructor<? extends Collection<E>> constructor;

public Adapter(
Gson context,
Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(context, elementTypeAdapter, elementType);
TypeAdapter<E> elementTypeAdapter, ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter = elementTypeAdapter;
this.constructor = constructor;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,19 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
}

Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawType);
TypeAdapter<?> keyAdapter = getKeyAdapter(gson, keyAndValueTypes[0]);
TypeAdapter<?> valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1]));
Type keyType = keyAndValueTypes[0];
Type valueType = keyAndValueTypes[1];
TypeAdapter<?> keyAdapter = getKeyAdapter(gson, keyType);
TypeAdapter<?> wrappedKeyAdapter =
new TypeAdapterRuntimeTypeWrapper<>(gson, keyAdapter, keyType);
TypeAdapter<?> valueAdapter = gson.getAdapter(TypeToken.get(valueType));
TypeAdapter<?> wrappedValueAdapter =
new TypeAdapterRuntimeTypeWrapper<>(gson, valueAdapter, valueType);
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

@SuppressWarnings({"unchecked", "rawtypes"})
// we don't define a type parameter for the key or value types
TypeAdapter<T> result =
new Adapter(
gson, keyAndValueTypes[0], keyAdapter, keyAndValueTypes[1], valueAdapter, constructor);
TypeAdapter<T> result = new Adapter(wrappedKeyAdapter, wrappedValueAdapter, constructor);
return result;
}

Expand All @@ -157,15 +161,11 @@ private final class Adapter<K, V> extends TypeAdapter<Map<K, V>> {
private final ObjectConstructor<? extends Map<K, V>> constructor;

public Adapter(
Gson context,
Type keyType,
TypeAdapter<K> keyTypeAdapter,
Type valueType,
TypeAdapter<V> valueTypeAdapter,
ObjectConstructor<? extends Map<K, V>> constructor) {
this.keyTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(context, keyTypeAdapter, keyType);
this.valueTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(context, valueTypeAdapter, valueType);
this.keyTypeAdapter = keyTypeAdapter;
this.valueTypeAdapter = valueTypeAdapter;
this.constructor = constructor;
}

Expand Down
4 changes: 2 additions & 2 deletions gson/src/main/java/com/google/gson/stream/JsonReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ public final Strictness getStrictness() {
* <p>The default nesting limit is {@value #DEFAULT_NESTING_LIMIT}.
*
* @throws IllegalArgumentException if the nesting limit is negative.
* @since $next-version$
* @since 2.12.0
* @see #getNestingLimit()
*/
public final void setNestingLimit(int limit) {
Expand All @@ -444,7 +444,7 @@ public final void setNestingLimit(int limit) {
/**
* Returns the nesting limit of this reader.
*
* @since $next-version$
* @since 2.12.0
* @see #setNestingLimit(int)
*/
public final int getNestingLimit() {
Expand Down
36 changes: 35 additions & 1 deletion gson/src/test/java/com/google/gson/GsonBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.util.Date;
import org.junit.Ignore;
import org.junit.Test;

/**
Expand Down Expand Up @@ -251,7 +252,10 @@ public void testSetStrictness() throws IOException {
public void testRegisterTypeAdapterForObjectAndJsonElements() {
String errorMessage = "Cannot override built-in adapter for ";
Type[] types = {
Object.class, JsonElement.class, JsonArray.class,
Object.class,
// TODO: Registering adapter for JsonElement is allowed (for now) for backward compatibility,
// see https://github.com/google/gson/issues/2787
// JsonElement.class, JsonArray.class,
};
GsonBuilder gsonBuilder = new GsonBuilder();
for (Type type : types) {
Expand All @@ -263,6 +267,22 @@ public void testRegisterTypeAdapterForObjectAndJsonElements() {
}
}

/**
* Verifies that (for now) registering adapter for {@link JsonElement} and subclasses is possible,
* but has no effect. See {@link #testRegisterTypeAdapterForObjectAndJsonElements()}.
*/
@Test
public void testRegisterTypeAdapterForJsonElements() {
Gson gson = new GsonBuilder().registerTypeAdapter(JsonArray.class, NULL_TYPE_ADAPTER).create();
TypeAdapter<JsonArray> adapter = gson.getAdapter(JsonArray.class);
// Does not use registered adapter
assertThat(adapter).isNotSameInstanceAs(NULL_TYPE_ADAPTER);
assertThat(adapter.toJson(new JsonArray())).isEqualTo("[]");
}

@Ignore(
"Registering adapter for JsonElement is allowed (for now) for backward compatibility, see"
+ " https://github.com/google/gson/issues/2787")
@Test
public void testRegisterTypeHierarchyAdapterJsonElements() {
String errorMessage = "Cannot override built-in adapter for ";
Expand All @@ -282,6 +302,20 @@ public void testRegisterTypeHierarchyAdapterJsonElements() {
gsonBuilder.registerTypeHierarchyAdapter(Object.class, NULL_TYPE_ADAPTER);
}

/**
* Verifies that (for now) registering hierarchy adapter for {@link JsonElement} and subclasses is
* possible, but has no effect. See {@link #testRegisterTypeHierarchyAdapterJsonElements()}.
*/
@Test
public void testRegisterTypeHierarchyAdapterJsonElements_Allowed() {
Gson gson =
new GsonBuilder().registerTypeHierarchyAdapter(JsonArray.class, NULL_TYPE_ADAPTER).create();
TypeAdapter<JsonArray> adapter = gson.getAdapter(JsonArray.class);
// Does not use registered adapter
assertThat(adapter).isNotSameInstanceAs(NULL_TYPE_ADAPTER);
assertThat(adapter.toJson(new JsonArray())).isEqualTo("[]");
}

@Test
public void testSetDateFormatWithInvalidPattern() {
GsonBuilder builder = new GsonBuilder();
Expand Down
10 changes: 6 additions & 4 deletions gson/src/test/java/com/google/gson/JsonArrayAsListSuiteTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ public Iterable<JsonElement> order(List<JsonElement> insertionOrder) {
@Override
public List<JsonElement> create(Object... elements) {
JsonArray array = new JsonArray();
// This is not completely accurate: Because there is no way to directly construct JsonArray or
// its List view with existing elements, this has to add the elements individually with
// `List#add`
var list = array.asList();
for (Object element : elements) {
array.add((JsonElement) element);
list.add((JsonElement) element);
}
return array.asList();
return list;
}
}

Expand All @@ -54,8 +58,6 @@ public static Test suite() {
return ListTestSuiteBuilder.using(new ListGenerator())
.withFeatures(
CollectionSize.ANY,
// Note: There is current a Guava bug which causes 'null additions' to not be tested if
// 'null queries' is enabled, see https://github.com/google/guava/issues/7401
CollectionFeature.ALLOWS_NULL_QUERIES,
CollectionFeature.RESTRICTS_ELEMENTS, // List only allows JsonElement
CollectionFeature.SUPPORTS_ADD,
Expand Down
10 changes: 6 additions & 4 deletions gson/src/test/java/com/google/gson/JsonObjectAsMapSuiteTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ public SampleElements<Entry<String, JsonElement>> samples() {
@Override
public Map<String, JsonElement> create(Object... elements) {
JsonObject object = new JsonObject();
// This is not completely accurate: Because there is no way to directly construct JsonObject
// or its Map view with existing entries, this has to add the entries individually with
// `Map#put`
var map = object.asMap();
for (Object element : elements) {
var entry = (Entry<?, ?>) element;
object.add((String) entry.getKey(), (JsonElement) entry.getValue());
map.put((String) entry.getKey(), (JsonElement) entry.getValue());
}
return object.asMap();
return map;
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -70,8 +74,6 @@ public static Test suite() {
return MapTestSuiteBuilder.using(new MapGenerator())
.withFeatures(
CollectionSize.ANY,
// Note: There is current a Guava bug which causes 'null additions' to not be tested if
// 'null queries' is enabled, see https://github.com/google/guava/issues/7401
MapFeature.ALLOWS_ANY_NULL_QUERIES,
MapFeature.RESTRICTS_KEYS, // Map only allows String keys
MapFeature.RESTRICTS_VALUES, // Map only allows JsonElement values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public MapGenerator(boolean allowNullValues) {

@Override
protected Map<String, String> create(Entry<String, String>[] entries) {
// This is not completely accurate: Because LinkedTreeMap has no constructor which accepts
// existing entries, this has to add the entries individually with `Map#put`
var map = new LinkedTreeMap<String, String>(allowNullValues);
for (var entry : entries) {
map.put(entry.getKey(), entry.getValue());
Expand All @@ -47,8 +49,6 @@ private static Feature<?>[] createFeatures(Feature<?>... additionalFeatures) {
new ArrayList<Feature<?>>(
List.of(
CollectionSize.ANY,
// Note: There is current a Guava bug which causes 'null additions' to not be tested
// if 'null queries' is enabled, see https://github.com/google/guava/issues/7401
MapFeature.ALLOWS_ANY_NULL_QUERIES,
MapFeature.RESTRICTS_KEYS, // Map only allows comparable keys
MapFeature.SUPPORTS_PUT,
Expand All @@ -74,7 +74,8 @@ public static Test suite() {
.named("nullValues=false")
.createTestSuite();

TestSuite testSuite = new TestSuite("LinkedTreeMap");
// Use qualified class name to make it easier to find this test class in the IDE
TestSuite testSuite = new TestSuite(LinkedTreeMapSuiteTest.class.getName());
testSuite.addTest(nullValuesSuite);
testSuite.addTest(nonNullValuesSuite);

Expand Down
2 changes: 1 addition & 1 deletion metrics/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<parent>
<groupId>com.google.code.gson</groupId>
<artifactId>gson-parent</artifactId>
<version>2.11.1-SNAPSHOT</version>
<version>2.12.1-SNAPSHOT</version>
</parent>

<artifactId>gson-metrics</artifactId>
Expand Down
Loading

0 comments on commit 3c1635d

Please sign in to comment.