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

  1. Check the actual type of the path result first (obj instanceof JsonArray || obj instanceof JsonObject, or use provider.isArray/isMap) before iterating
  2. Adjust the JsonPath to select a container, e.g. use '$.field[*]' or '$.field.arrayProperty' instead of a scalar property
  3. Catch UnsupportedOperationException and treat the value as a scalar: wrap it in a single-element list instead of iterating
  4. 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

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


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/106188f0d481820a. Report an issue: GitHub.