FasterXML / FasterXML/jackson-jakarta-rs-providers

`ProviderBase.readFrom()` fails to advance past `START_ARRAY` for `MappingIterator` with JSON array input

Open
#69 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
20
Forks
16
Avg merge
10h 4m
Merged PRs (30d)
1

Description

### Description

ProviderBase.readFrom() does not handle JSON array input when the entity type is MappingIterator. The method calls p.nextToken() which positions the parser at START_ARRAY, then passes it to reader.readValues(p). However, readValues(JsonParser) creates a MappingIterator with managedParser=false, which does not auto-skip START_ARRAY.

The ObjectReader.readValues(JsonParser) Javadoc explicitly states:

> for wrapped sequences, parser MUST NOT point to the surrounding START_ARRAY but rather to the token following it.

This means JSON array input like `[{"x":1}, {"x":2}]` fails with a `MismatchedInputException`, while NDJSON input like `{"x":1}\n{"x":2}` works fine.

### Steps to Reproduce

Create a Jakarta REST resource method with a `MappingIterator` parameter:

```java
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public List process(MappingIterator points) {
List result = new ArrayList<>();
while (points.hasNext()) {
result.add(points.next());
}
return result;
}
```

```
POST a JSON array:

Content-Type: application/json

[{"x": 1, "y": 2}, {"x": 3, "y": 4}]

```

Expected: Successfully iterates over the two Point objects.

Actual: Throws `MismatchedInputException: Cannot deserialize value of type Point from Array value (token START_ARRAY).`

Root Cause

In `ProviderBase.readFrom()`:

```java
if (p == null || p.nextToken() == null) { // positions at START_ARRAY for array input
// ...
}
// ...
if (multiValued) {
return reader.readValues(p); // passes parser still at START_ARRAY
}
```

`readValues(JsonParser)` calls `_newIterator(p, ctxt, deser, false)` — the `false` means `managedParser=false`, so `MappingIterator`'s constructor does not skip `START_ARRAY`:

```java
if (managedParser && p.isExpectedStartArrayToken()) {
p.clearCurrentToken(); // only reached when managedParser=true
}
```

The existing test (`testMappingIterator` in `SimpleEndpointTestBase`) only sends NDJSON, so this path was never exercised.

Suggested Fix

Advance past `START_ARRAY` before calling `readValues(p)`:

```java
if (multiValued) {
if (p.currentToken() == JsonToken.START_ARRAY) {
p.nextToken();
}
return reader.readValues(p);
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.