{"record":{"id":"a5afec79f978d1e3","repo":"jwtk/jjwt","slug":"deserialized-data-is-not-a-json-object-cannot-cre","errorCode":null,"errorMessage":"Deserialized data is not a JSON Object; cannot create Map<String,?>","messagePattern":"Deserialized data is not a JSON Object; cannot create Map<String,\\?>","errorType":"validation","errorClass":"io.jsonwebtoken.io.DeserializationException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/io/JsonObjectDeserializer.java","lineNumber":59,"sourceCode":"\n    public JsonObjectDeserializer(Deserializer<?> deserializer, String name) {\n        this.deserializer = Assert.notNull(deserializer, \"JSON Deserializer cannot be null.\");\n        this.name = Assert.hasText(name, \"name cannot be null or empty.\");\n    }\n\n    @Override\n    public Map<String, ?> apply(Reader in) {\n        Assert.notNull(in, \"InputStream argument cannot be null.\");\n        Object value;\n        try {\n            value = this.deserializer.deserialize(in);\n            if (value == null) {\n                String msg = \"Deserialized data resulted in a null value; cannot create Map<String,?>\";\n                throw new DeserializationException(msg);\n            }\n            if (!(value instanceof Map)) {\n                String msg = \"Deserialized data is not a JSON Object; cannot create Map<String,?>\";\n                throw new DeserializationException(msg);\n            }\n            // JSON Specification requires all JSON Objects to have string-only keys.  So instead of\n            // checking that the val.keySet() has all Strings, we blindly cast to a Map<String,?>\n            // since input would rarely, if ever, have non-string keys.\n            //noinspection unchecked\n            return (Map<String, ?>) value;\n        } catch (StackOverflowError e) {\n            String msg = String.format(MALFORMED_COMPLEX_ERROR, this.name, this.name, e.getMessage());\n            throw new DeserializationException(msg, e);\n        } catch (Throwable t) {\n            throw malformed(t);\n        }\n    }\n\n    protected RuntimeException malformed(Throwable t) {\n        String msg = String.format(MALFORMED_ERROR, this.name, t.getMessage());\n        throw new MalformedJwtException(msg, t);\n    }","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/io/JsonObjectDeserializer.java#L41-L77","documentation":"Thrown as a DeserializationException when the input deserializes successfully but is not a JSON object (e.g. a JSON array, string, or number), so it cannot be treated as Map<String,?>. JSON parsing in JJWT expects the top-level value to be an object.","triggerScenarios":"Deserializing input whose top-level JSON value is an array ('[...]'), a bare string, number, or boolean rather than an object ('{...}').","commonSituations":"Passing a JWT payload that is a JSON array; feeding a JSON array body (e.g. a list of claims) where a claims object is required; concatenating or mis-splitting JWT segments so the wrong bytes are deserialized.","solutions":["Verify the input begins with '{' and is a valid JSON object at the top level.","If the data is a JSON array, wrap it in an object or deserialize it with a List-typed deserializer instead.","Check JWT parsing logic: ensure only the payload segment (not header or signature) is being deserialized as claims.","Log the raw input when debugging to see the actual top-level JSON structure."],"exampleFix":"// before\nbyte[] payload = \"[1,2,3]\".getBytes(); // JSON array, not object\nMap<String,?> claims = deserializer.deserialize(new ByteArrayInputStream(payload));\n// after\nbyte[] payload = \"{\\\"items\\\":[1,2,3]}\".getBytes(); // wrap array in an object\nMap<String,?> claims = deserializer.deserialize(new ByteArrayInputStream(payload));","handlingStrategy":"type-guard","validationCode":"// Java\nString s = new String(payload, StandardCharsets.UTF_8).trim();\nif (!s.startsWith(\"{\")) {\n    throw new IllegalArgumentException(\"payload is not a JSON object\");\n}","typeGuard":"static boolean isJsonObjectPayload(byte[] bytes) {\n    if (bytes == null || bytes.length == 0) return false;\n    String s = new String(bytes, StandardCharsets.UTF_8).trim();\n    return s.startsWith(\"{\") && s.endsWith(\"}\");\n}","tryCatchPattern":"try {\n    Map<String,?> claims = deserializer.apply(in);\n} catch (DeserializationException e) {\n    throw new IllegalArgumentException(\"Top-level JSON must be an object\", e);\n}","preventionTips":["Ensure JWT payloads are JSON objects, never bare arrays or scalars.","Split compact JWTs correctly — deserialize only the payload segment.","Validate the leading character of the payload before deserializing.","When handling arrays of claims, wrap them in a containing object."],"tags":["json","deserialization","type-mismatch"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}