json-path/JsonPath · error · UnsupportedOperationException
an array or object instance is expected
Error message
an array or object instance is expected
What it means
JakartaJsonProvider.toIterable() converts a JSON value into an Iterable of unwrapped Java objects. It only supports JsonArray (or JsonArrayBuilder) and JsonObject (or JsonObjectBuilder) inputs; anything else — a scalar string, number, boolean, or null — triggers UnsupportedOperationException('an array or object instance is expected'). The library throws it because iteration is only defined over the two JSON container types.
Source
Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/json/JakartaJsonProvider.java:304
List<Object> values;
if (isArray(obj)) {
if (obj instanceof JsonArrayBuilder) {
obj = ((JsonArrayBuilder) obj).build();
}
values = new ArrayList<Object>(((List<?>) obj).size());
for (Object val : ((List<?>) obj)) {
values.add(unwrap(val));
}
} else if (isMap(obj)) {
if (obj instanceof JsonObjectBuilder) {
obj = ((JsonObjectBuilder) obj).build();
}
values = new ArrayList<Object>(((JsonObject) obj).size());
for (JsonValue val : ((JsonObject) obj).values()) {
values.add(unwrap(val));
}
} else {
throw new UnsupportedOperationException("an array or object instance is expected");
}
return values;
}
@Override
public Object unwrap(Object obj) {
if (obj == null) {
return null;
}
if (!(obj instanceof JsonValue)) {
return obj;
}
switch (((JsonValue) obj).getValueType()) {
case ARRAY:
if (mutableJson && obj instanceof JsonArrayProxy) {
return (JsonArray) obj;
} else {
return ((JsonArray) obj).getValuesAs((JsonValue v) -> unwrap(v));
View on GitHub (pinned to 62a4c9f0f6)
Solutions
- Check the actual type of the path result first (obj instanceof JsonArray || obj instanceof JsonObject, or use provider.isArray/isMap) before iterating
- Adjust the JsonPath to select a container, e.g. use '$.field[*]' or '$.field.arrayProperty' instead of a scalar property
- Catch UnsupportedOperationException and treat the value as a scalar: wrap it in a single-element list instead of iterating
- If the value is legitimately nullable, guard null before calling paths that force iteration
Example fix
// before
Iterable<Object> vals = JsonPath.parse(json).read("$.items"); // $.items is "foo"
// after
Object res = JsonPath.parse(json).read("$.items");
Iterable<Object> vals = (res instanceof List || res instanceof Map)
? JsonPath.parse(json).read("$.items")
: java.util.Collections.singletonList(res); Defensive patterns
Strategy: type-guard
Validate before calling
// Java
private static boolean isIterableContainer(Object obj) {
return obj instanceof List || obj instanceof Map || obj instanceof JsonArray || obj instanceof JsonObject;
} Type guard
if (obj instanceof JsonArray || obj instanceof JsonArrayBuilder || obj instanceof JsonObject || obj instanceof JsonObjectBuilder) {
// safe to iterate via provider.toIterable(obj)
} else {
// treat as scalar: singletonList(obj)
} Try / catch
try {
Iterable<?> it = provider.toIterable(obj);
} catch (UnsupportedOperationException e) {
Iterable<?> it = Collections.singletonList(obj);
} Prevention
- Prefer wildcard paths ($.items[*]) so results are always arrays
- Inspect getValueType() on JsonValue results before iterating
- When reading scalars, use read(path, Class) instead of iterating
- Centralize path reading behind a helper that normalizes scalars to lists
When it happens
Trigger: Evaluating a JsonPath (e.g. with JsonPath.using(JakartaJsonProvider...).read(path)) whose result is a scalar like '$.name' or '$' pointing at a string/number/boolean/null, then iterating the result; calling toIterable(obj) directly with a non-container value; applying wildcard/deep-scan paths whose provider internals call toIterable on a leaf node.
Common situations: Paths written expecting an array but the document actually holds a scalar (API changed shape); reading '$.field' instead of '$.field[*]'; a null JSON value being iterated; using the Jakarta EE JSON-P provider against documents where the target of the path is a primitive.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot create JSON element from null
- Use map() method to databind a JsonObject
- JSON-P adapter does not support getLocation()
- Put can not be performed to multiple properties
- Rename can not be performed to multiple properties
AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11).
Data as JSON: /api/errors/106188f0d481820a.
Report an issue: GitHub.