json-path/JsonPath · error · MappingException

JSON array cannot be mapped to " + className

Error message

JSON array cannot be mapped to " + className

What it means

When mapping a JSON array, newCollectionOfType() instantiates the requested Collection target type: concrete classes need a public no-arg constructor, and known interfaces (List, Set, Queue) are mapped to LinkedList/LinkedHashSet. If the target type is not a Collection subtype (e.g. Map or a POJO) or is an unrecognized Collection interface such as SortedSet or Deque, it throws MappingException because a JSON array cannot be materialized into that type.

Source

Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java:310

     * @return instance of collection type identified by the argument
     * @throws MappingException on a type that cannot be safely instantiated
     */
    private Collection<Object> newCollectionOfType(Class<?> collectionType) throws MappingException {
        if (Collection.class.isAssignableFrom(collectionType)) {
            if (!collectionType.isInterface()) {
                @SuppressWarnings("unchecked")
                Collection<Object> coll = (Collection<Object>) newNoArgInstance(collectionType);
                return coll;
            } else if (List.class.isAssignableFrom(collectionType)) {
                return new java.util.LinkedList<Object>();
            } else if (Set.class.isAssignableFrom(collectionType)) {
                return new java.util.LinkedHashSet<Object>();
            } else if (Queue.class.isAssignableFrom(collectionType)) {
                return new java.util.LinkedList<Object>();
            }
        }
        String className = collectionType.getSimpleName();
        throw new MappingException("JSON array cannot be mapped to " + className);
    }

    /**
     * Lists all publicly accessible constructors for the {@code Class}
     * identified by the argument, including any constructors inherited
     * from superclasses, and uses a no-args constructor, if available,
     * to create a new instance of the class. If argument is interface, 
     * this method returns {@code null}.
     * 
     * @param targetType class type to create instance of
     * @return an instance of the class represented by the argument
     * @throws MappingException if no-arg public constructor is not there 
     */
    private Object newNoArgInstance(Class<?> targetType) throws MappingException {
        if (targetType.isInterface()) {
            return null;
        } else {
            for (Constructor<?> ctr : targetType.getConstructors()) {

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Map the JSON array into a supported target: List.class, Set.class, Queue.class, or a concrete Collection class with a public no-arg constructor (e.g. ArrayList.class).
  2. If you need Deque/SortedSet/etc., read into a supported interface first and convert: new java.util.TreeSet<>(jsonPath.read(path, List.class)).
  3. Ensure the element type is conveyed via TypeRef, e.g. new TypeRef<List<Book>>(){}, so collection creation and element mapping both work.
  4. If the target should be a single object rather than a collection, the JSON at that path must be an object, not an array — fix the path or the expected type.

Example fix

// before
List<Book> books = jsonPath.read("$.store.book", SortedSet.class); // MappingException
// after
List<Book> books = jsonPath.read("$.store.book", new TypeRef<List<Book>>() {});
SortedSet<Book> sorted = new TreeSet<>(books);
Defensive patterns

Strategy: validation

Validate before calling

static boolean mappableArrayTarget(Class<?> t) {
    return java.util.Collection.class.isAssignableFrom(t)
        && (!t.isInterface() || java.util.List.class.isAssignableFrom(t)
            || java.util.Set.class.isAssignableFrom(t)
            || java.util.Queue.class.isAssignableFrom(t));
}

Try / catch

try {
    return jsonPath.read(path, targetType);
} catch (MappingException e) {
    return new ArrayList<>(jsonPath.read(path, List.class));
}

Prevention

When it happens

Trigger: read("$.items", SomeNonCollectionClass.class) where the path points to a JSON array and the class is not Collection-assignable, or requesting a Collection interface not handled by the if/else chain (e.g. SortedSet.class, Deque.class, Iterable.class), including via TypeRef/ParameterizedType whose raw type falls through.

Common situations: Typos in the target class; assuming all java.util Collection interfaces are supported (only List/Set/Queue branches exist, so SortedSet/Deque fail); trying to map an array directly into Map.class or a bean class; using a custom collection type without a no-arg constructor.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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