json-path/JsonPath · error · JsonException
Cannot create JSON iterator for " + value
Error message
Cannot create JSON iterator for " + value
What it means
createScope() in JakartaMappingProvider's JsonStructureToParserAdapter can only iterate JsonArray and JsonObject structures. If it is handed any other JsonValue (a scalar like JsonString, JsonNumber, JsonValue.TRUE/FALSE/NULL), it throws JsonException because no container iterator exists for scalars. This is called by the adapter constructor and by next() when advancing into nested values.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java:545
while (scope.hasNext()) {
scope.next();
}
state = Event.END_OBJECT;
}
}
@Override
public void close() {
// JSON objects are read-only
}
private JsonStructureScope createScope(JsonValue value) {
if (value instanceof JsonArray) {
return new JsonArrayScope((JsonArray) value);
} else if (value instanceof JsonObject) {
return new JsonObjectScope((JsonObject) value);
}
throw new JsonException("Cannot create JSON iterator for " + value);
}
private Event getState(JsonValue value) {
switch (value.getValueType()) {
case ARRAY:
return Event.START_ARRAY;
case OBJECT:
return Event.START_OBJECT;
case STRING:
return Event.VALUE_STRING;
case NUMBER:
return Event.VALUE_NUMBER;
case TRUE:
return Event.VALUE_TRUE;
case FALSE:
return Event.VALUE_FALSE;
case NULL:
return Event.VALUE_NULL;
View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Wrap or normalize scalars before mapping — ensure the value passed to map/toJson is a JsonObject or JsonArray
- Refine the JsonPath so it returns a structure, or read scalar results directly instead of via the streaming adapter
- Catch JsonException and handle scalar results as leaf values in your code
Example fix
// before
Object doc = Json.createObjectBuilder().build();
JsonValue scalar = jsonPath.read(doc); // may be a JsonString
mapper.map(scalar, ...); // JsonException
// after
JsonValue scalar = jsonPath.read(doc);
if (scalar instanceof JsonStructure) {
mapper.map(scalar, ...);
} else {
Object v = unwrapScalar(scalar); // handle string/number/bool/null directly
} Defensive patterns
Strategy: validation
Validate before calling
if (!(value instanceof JsonStructure)) {
throw new IllegalArgumentException("Expected JsonObject or JsonArray, got: " + value.getValueType());
} Type guard
boolean isIterableStructure(JsonValue v) {
return v instanceof JsonArray || v instanceof JsonObject;
} Try / catch
try {
mapper.map(value, typeRef, config);
} catch (JsonException e) {
// value was a scalar; unwrap or wrap it before mapping
} Prevention
- Only feed JsonObject/JsonArray roots into the streaming adapter
- Handle scalar JsonPath results (strings, numbers, booleans, null) as leaf values outside the adapter
- Write unit tests covering both container and scalar read results
When it happens
Trigger: Driving the adapter with a root or nested JsonValue that is a scalar (string, number, true, false, null) rather than a JsonObject or JsonArray — e.g. mapping the result of a JSON-P query that selected a single scalar.
Common situations: A JsonPath expression like $.name or $[0] that resolves to a scalar is fed to the Jakarta mapping provider, which expects a JSON structure at the root; upgrading providers so a previously object/array root is now scalar.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- JSON array cannot be mapped to " + className
- Cannot map JSON element to " + typeName
- JSON-P adapter does not support getLocation()
- Unknown value type " + value.getValueType()
- Can only rename properties in a map
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/63ac4ac1a84e28ca.
Report an issue: GitHub.