json-path/JsonPath · error · MappingException

JSON boolean (false) cannot be mapped to " + className

Error message

JSON boolean (false) cannot be mapped to " + className

What it means

JakartaMappingProvider.mapImpl converts a JSON-P JsonValue into a Java type. When the source is JsonValue.FALSE and the requested targetType is anything other than Boolean (or boolean via earlier checks), it cannot convert and throws MappingException. This is a deliberate strictness: the provider does not coerce booleans to strings, numbers, or objects.

Source

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

    private Object mapImpl(Object source, final Type targetType) {
        if (source == null || source == JsonValue.NULL) {
            return null;
        }
        if (source == JsonValue.TRUE) {
            if (Boolean.class.equals(targetType)) {
                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();

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Change the requested target type to Boolean.class (or boolean) so the false value maps directly
  2. Fix the JSON path to select a value of the expected type, or verify the document shape at the path
  3. Use .map(...) with a custom conversion lambda instead of direct type mapping
  4. Configure a different MappingProvider (e.g. JsonSmartMappingProvider) if lenient coercion is desired

Example fix

// before
String enabled = context.read("$.enabled", String.class); // MappingException
// after
Boolean enabled = context.read("$.enabled", Boolean.class);
Defensive patterns

Strategy: type-guard

Validate before calling

Object raw = ctx.read(path);
if (!(raw instanceof Boolean)) throw new IllegalStateException(path + " is not a JSON boolean: " + raw);
Boolean b = ctx.read(path, Boolean.class);

Type guard

boolean isBoolean(Object v) { return v instanceof Boolean || v == Boolean.FALSE || v == Boolean.TRUE; }

Try / catch

try {
    Boolean b = ctx.read(path, Boolean.class);
} catch (MappingException e) {
    // fall back to raw read and convert
    Object raw = ctx.read(path);
}

Prevention

When it happens

Trigger: Calling JsonPath.parse(json).read(path, Class) (or .map(...) / mapping via the provider) where the JSON value at the path is literally false and the requested target type is not Boolean.class/boolean — e.g. read("$.enabled", String.class) or read("$.flag", Integer.class).

Common situations: Path points at a boolean field while a String/numeric type was assumed (API schema changed true/false into an enum-like field); config where a flag is expected to be a string "false" but the document contains real JSON false; switching from the default JsonSmartMappingProvider (looser coercions) to JakartaMappingProvider and old coercions now fail.

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/0be1fcba7499b424. Report an issue: GitHub.