json-path/JsonPath · error · MappingException

JSON string cannot be mapped to " + className

Error message

JSON string cannot be mapped to " + className

What it means

JakartaMappingProvider.mapImpl throws this when the source JsonValue is a JsonString but the requested targetType is not String (and not char sequence types handled elsewhere). The provider performs no automatic string coercion, so a JSON string cannot be mapped to e.g. Integer or Boolean.

Source

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

                return Boolean.TRUE;
            } else {
                String className = targetType.toString();
                throw new MappingException("JSON boolean (true) cannot be mapped to " + className);
            }
        }
        if (source == JsonValue.FALSE) {
            if (Boolean.class.equals(targetType)) {
                return Boolean.FALSE;
            } else {
                String className = targetType.toString();
                throw new MappingException("JSON boolean (false) cannot be mapped to " + className);
            }
        } else if (source instanceof JsonString) {
            if (String.class.equals(targetType)) {
                return ((JsonString) source).getChars();
            } else {
                String className = targetType.toString();
                throw new MappingException("JSON string cannot be mapped to " + className);
            }
        } else if (source instanceof JsonNumber) {
            JsonNumber jsonNumber = (JsonNumber) source;
            if (jsonNumber.isIntegral()) {
                return mapIntegralJsonNumber(jsonNumber, getRawClass(targetType));
            } else {
                return mapDecimalJsonNumber(jsonNumber, getRawClass(targetType));
            }
        }
        if (source instanceof JsonArrayBuilder) {
            source = ((JsonArrayBuilder) source).build();
        } else if (source instanceof JsonObjectBuilder) {
            source = ((JsonObjectBuilder) source).build();
        }
        if (source instanceof Collection) {
            // this covers both List<JsonValue> and JsonArray from JSON-P spec
            Class<?> rawTargetType = getRawClass(targetType);
            Type targetTypeArg = getFirstTypeArgument(targetType);

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Request String.class and parse manually (Integer.parseInt, Boolean.parseBoolean)
  2. Correct the JSON path so it selects a non-string value of the expected type
  3. Use .map(...) with a custom converter that parses the string
  4. Switch to a lenient MappingProvider if implicit coercion is acceptable

Example fix

// before
int port = context.read("$.port", int.class); // "8080" -> MappingException
// after
int port = Integer.parseInt(context.read("$.port", String.class));
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Calling read(path, SomeClass) where the JSON value at the path is a quoted string but the target class is not String — e.g. read("$.port", Integer.class) when the document contains "8080".

Common situations: Documents where numeric-looking values are quoted (IDs, ports); expecting automatic parse of "true"/"false" or "123" into primitives; migrating from a lenient mapping provider that coerced strings to numbers/booleans.

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


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