FasterXML / FasterXML/jackson-jakarta-rs-providers
`ProviderBase.readFrom()` fails to advance past `START_ARRAY` for `MappingIterator` with JSON array input
- 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.