google / google/gson

AtomicIntegerArray deserializer crashes on JSON null (IllegalStateException) — symmetric fix to #3038

Open Beginner friendly
#3,047 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
24.2k
Forks
4.5k
Avg merge
6d 4h
Merged PRs (30d)
12

Description

## Bug

Deserializing a JSON array that contains a `null` element into an `AtomicIntegerArray` crashes with an uncaught `IllegalStateException`:

```java
new Gson().fromJson("[1,null,3]", AtomicIntegerArray.class);
// throws IllegalStateException: Expected an int but was NULL at line 1 column 4 path $[1]
```

## Root cause

In `TypeAdapters.java`, the `ATOMIC_INTEGER_ARRAY` adapter's `read()` method calls `in.nextInt()` inside a loop that only catches `NumberFormatException`:

```java
public AtomicIntegerArray read(JsonReader in) throws IOException {
List list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
try {
int integer = in.nextInt();
list.add(integer);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
in.endArray();
...
}
```

When the `JsonReader` is positioned at a `NULL` token, `nextInt()` throws `IllegalStateException` — which is **not** caught here, so it propagates raw instead of being converted to a `JsonSyntaxException`.

## Relationship to #3038

PR #3038 (merged 2026-06-22) fixed the symmetric issue in `AtomicLongArray`. That adapter delegates to `longAdapter.read(in)`, which returns `null` for a JSON null; the fix added an explicit null-check:

```java
Number value = longAdapter.read(in);
if (value == null) {
throw new JsonSyntaxException("null is not a valid AtomicLongArray element");
}
list.add(value.longValue());
```

`AtomicIntegerArray` was not updated with the same treatment.

## Expected behaviour

A JSON null element inside an `AtomicIntegerArray` should throw a `JsonSyntaxException` (same as `AtomicLongArray` after #3038), not a raw `IllegalStateException`.

## Suggested fix

Mirror the approach used in the `AtomicLongArray` adapter — either:

**Option A** — peek before reading:
```java
while (in.hasNext()) {
try {
if (in.peek() == com.google.gson.stream.JsonToken.NULL) {
throw new JsonSyntaxException("null is not a valid AtomicIntegerArray element");
}
int integer = in.nextInt();
list.add(integer);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
```

**Option B** — delegate to `INTEGER` type adapter (returns `null` for JSON null, already handles this safely) and add a null-check, consistent with the `AtomicLongArray` pattern.

A regression test analogous to the one added in #3038 for `AtomicLongArray` should also be added.

## Environment

- Gson latest main branch (after #3038 merge)
- Reproducible with any Gson version where `AtomicIntegerArray` deserialization is supported

Contributor guide

Open the contributing guide

Research direction

Start in TypeAdapters.java by comparing the ATOMIC_INTEGER_ARRAY adapter with the AtomicLongArray change from PR #3038. Run the existing AtomicLongArray regression test as a guide, add an analogous test for a null element in AtomicIntegerArray, and confirm it produces JsonSyntaxException rather than IllegalStateException.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.