json-path/JsonPath · error · MappingException

JSON decimal number cannot be mapped to " + className

Error message

JSON decimal number cannot be mapped to " + className

What it means

mapDecimalJsonNumber converts a JSON decimal (non-integral) number to Float/Double/BigDecimal (and primitive variants). Any other target type throws MappingException with the target's simple name — e.g. requesting Integer or String for a value like 3.14.

Source

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

    @SuppressWarnings("unchecked")
    private <T> T mapDecimalJsonNumber(JsonNumber jsonNumber, Class<?> targetType) {
        if (targetType.isPrimitive()) {
            if (float.class.equals(targetType)) {
                return (T) new Float(jsonNumber.doubleValue());
            } else if (double.class.equals(targetType)) {
                return (T) Double.valueOf(jsonNumber.doubleValue());
            }
        } else if (Float.class.equals(targetType)) {
            return (T) new Float(jsonNumber.doubleValue());
        } else if (Double.class.equals(targetType)) {
            return (T) Double.valueOf(jsonNumber.doubleValue());
        } else if (BigDecimal.class.equals(targetType)) {
            return (T) jsonNumber.bigDecimalValue();
        }

        String className = targetType.getSimpleName();
        throw new MappingException("JSON decimal number cannot be mapped to " + className);
    }

    private Object unwrapJsonValue(Object jsonValue) {
        if (jsonValue == null) {
            return null;
        }
        if (!(jsonValue instanceof JsonValue)) {
            return jsonValue;
        }
        switch (((JsonValue) jsonValue).getValueType()) {
        case ARRAY:
        	// TODO do we unwrap JsonObjectArray proxies?
            //return ((JsonArray) jsonValue).getValuesAs(JsonValue.class);
            return ((JsonArray) jsonValue).getValuesAs((JsonValue v) -> unwrapJsonValue(v));
        case OBJECT:
            throw new IllegalArgumentException("Use map() method to databind a JsonObject");
        case STRING:
            return ((JsonString) jsonValue).getString();

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Request Double.class, Float.class or BigDecimal.class instead of the unsupported type
  2. Read as BigDecimal and convert explicitly (intValue(), longValue(), toPlainString())
  3. Use .map(...) with a custom conversion function
  4. Adjust the path or document so the value's numeric shape matches the target

Example fix

// before
int n = ctx.read("$.ratio", int.class); // 1.5 -> MappingException
// after
int n = ctx.read("$.ratio", BigDecimal.class).intValue();
Defensive patterns

Strategy: type-guard

Validate before calling

Object raw = ctx.read(path);
if (!(raw instanceof Number)) throw new IllegalStateException(path + " is not numeric");
Double d = ctx.read(path, Double.class);

Type guard

boolean isDecimalNumber(Object v) { return v instanceof Double || v instanceof Float || v instanceof BigDecimal; }

Try / catch

try {
    Double d = ctx.read(path, Double.class);
} catch (MappingException e) {
    BigDecimal bd = ctx.read(path, BigDecimal.class);
    double d2 = bd.doubleValue();
}

Prevention

When it happens

Trigger: read(path, Integer.class) or read(path, String.class) where the JSON value is a decimal number; read(path, MyClass.class) on a JSON fractional number.

Common situations: Documents where a value that is usually integral occasionally arrives as 1.0/1.5, so the Integer-typed read fails; expecting strings or custom types from JSON decimals; provider switch removing implicit narrowing/coercion.

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/5a12e5054f3d7257. Report an issue: GitHub.