{"record":{"id":"3fd88ddd1daed5ec","repo":"json-path/JsonPath","slug":"use-map-method-to-databind-a-jsonobject","errorCode":null,"errorMessage":"Use map() method to databind a JsonObject","messagePattern":"Use map\\(\\) method to databind a JsonObject","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java","lineNumber":258,"sourceCode":"\r\n        String className = targetType.getSimpleName();\r\n        throw new MappingException(\"JSON decimal number cannot be mapped to \" + className);\r\n    }\r\n\r\n    private Object unwrapJsonValue(Object jsonValue) {\r\n        if (jsonValue == null) {\r\n            return null;\r\n        }\r\n        if (!(jsonValue instanceof JsonValue)) {\r\n            return jsonValue;\r\n        }\r\n        switch (((JsonValue) jsonValue).getValueType()) {\r\n        case ARRAY:\r\n        \t// TODO do we unwrap JsonObjectArray proxies?\r\n            //return ((JsonArray) jsonValue).getValuesAs(JsonValue.class);\r\n            return ((JsonArray) jsonValue).getValuesAs((JsonValue v) -> unwrapJsonValue(v));\r\n        case OBJECT:\r\n            throw new IllegalArgumentException(\"Use map() method to databind a JsonObject\");\r\n        case STRING:\r\n            return ((JsonString) jsonValue).getString();\r\n        case NUMBER:\r\n            if (((JsonNumber) jsonValue).isIntegral()) {\r\n                //return ((JsonNumber) jsonValue).bigIntegerValueExact();\r\n                try {\r\n                    return ((JsonNumber) jsonValue).intValueExact();\r\n                } catch (ArithmeticException e) {\r\n                    return ((JsonNumber) jsonValue).longValueExact();\r\n                }\r\n            } else {\r\n                //return ((JsonNumber) jsonValue).bigDecimalValue();\r\n                return ((JsonNumber) jsonValue).doubleValue();\r\n            }\r\n        case TRUE:\r\n            return Boolean.TRUE;\r\n        case FALSE:\r\n            return Boolean.FALSE;\r","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/spi/mapper/JakartaMappingProvider.java#L240-L276","documentation":"JakartaMappingProvider.unwrapJsonValue() converts JSON-P JsonValue leaves (strings, numbers, booleans, arrays) into plain Java objects. When it encounters a JsonObject (a nested JSON object), it deliberately refuses and throws IllegalArgumentException, because objects cannot be safely auto-flattened and must instead be databound to a target class via the provider's map() method. This is an intentional design boundary, not a data corruption bug.","triggerScenarios":"Calling JsonPath.parse(...).read(\"$.path\") (i.e. map()/unwrap path) on a JSON-P document where the addressed value is a JsonObject, or reading a JSON array whose elements are objects via a path that causes unwrapJsonValue to be applied to an object element (see JsonArray.getValuesAs(unwrapJsonValue) at line 256).","commonSituations":"Reading $.store.book[0] or any object-valued path without a target class; iterating an array of objects while expecting unwrapped Maps; switching MappingProvider from the default (which returns Maps) to the Jakarta JSON-P provider, where object nodes are no longer represented as java.util.Map; forgetting that this provider only unwraps scalar leaves and arrays.","solutions":["Request a concrete target type so the map() databinding path is used: read(\"$.store.book[0]\", Book.class) or read(path, new TypeRef<Map<String,Object>>(){}) instead of a bare read(path).","If you want raw structure back, wrap the read in map(..., JsonValue.class) or obtain the underlying JsonObject directly from the JsonStructure document and navigate it with the JSON-P API.","Cast/adjust code that assumed read(path) returns Map<String,Object> for object nodes; with this provider objects must be databound explicitly.","As a last resort catch IllegalArgumentException and fall back to the databind path, but prefer fixing the read call."],"exampleFix":"// before\nObject book = jsonPath.read(\"$.store.book[0]\"); // IllegalArgumentException: Use map() method to databind a JsonObject\n// after\nMap<String, Object> book = jsonPath.read(\"$.store.book[0]\", new TypeRef<Map<String, Object>>() {});","handlingStrategy":"type-guard","validationCode":"JsonValue v = (JsonValue) jsonPath.json();\nif (((JsonObject) ((JsonArray) v).getValue(0)).getValueType() == JsonValue.ValueType.OBJECT) {\n    // must use databind: read(path, Target.class)\n}","typeGuard":"boolean needsDatabind(Object v) {\n    return v instanceof JsonValue && ((JsonValue) v).getValueType() == JsonValue.ValueType.OBJECT;\n}","tryCatchPattern":"try {\n    Object o = jsonPath.read(path);\n} catch (IllegalArgumentException e) {\n    Object o = jsonPath.read(path, Map.class);\n}","preventionTips":["Never call bare read(path) on paths that resolve to JSON objects with this provider; always pass a target class or TypeRef.","Remember JakartaMappingProvider only auto-unwraps scalars and arrays; objects go through map().","Add a unit test asserting the shape returned by each read call after switching MappingProvider."],"tags":["json","databind","json-path","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}