{"record":{"id":"e91a3d8de19a2165","repo":"hibernate/hibernate-orm","slug":"malformed-json-expected-object-but-got-event","errorCode":null,"errorMessage":"Malformed JSON. Expected object but got: \" + event","messagePattern":"Malformed JSON\\. Expected object but got: \" \\+ event","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java","lineNumber":229,"sourceCode":"\t/**\n\t * Deserialize a JSON value to Java Object\n\t * @param embeddableMappingType the mapping type\n\t * @param reader the JSON reader\n\t * @param returnEmbeddable do we return an Embeddable object or array of Objects\n\t * @param options wrappping options\n\t * @return the deserialized value\n\t */\n\tpublic static <X> X deserialize(\n\t\t\tEmbeddableMappingType embeddableMappingType,\n\t\t\tJsonDocumentReader reader,\n\t\t\tboolean returnEmbeddable,\n\t\t\tWrapperOptions options) throws SQLException {\n\t\tfinal JsonDocumentItemType event;\n\t\tif ( !reader.hasNext() || ( event = reader.next() ) == JsonDocumentItemType.NULL_VALUE ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( event != JsonDocumentItemType.OBJECT_START ) {\n\t\t\tthrow new IllegalArgumentException(\"Malformed JSON. Expected object but got: \" + event);\n\t\t}\n\t\tfinal X result = consumeJsonDocumentItems( reader, embeddableMappingType, returnEmbeddable, options );\n\t\tassert !reader.hasNext();\n\t\treturn result;\n\t}\n\n\n\t// This is also used by Hibernate Reactive\n\tpublic static <X> X arrayFromString(\n\t\t\tJavaType<X> javaType,\n\t\t\tJdbcType elementJdbcType,\n\t\t\tString string,\n\t\t\tWrapperOptions options) throws SQLException {\n\t\tif ( string == null ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn deserializeArray( javaType, elementJdbcType, new StringJsonDocumentReader( string ), options );\n\t}","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JsonHelper.java#L211-L247","documentation":"JsonHelper.deserialize expects the top-level element of a JSON-mapped column to be an object (the representation of an embeddable). If the reader yields anything else - an array, string, number, boolean - it throws IllegalArgumentException('Malformed JSON. Expected object but got: <event>'). The document is valid JSON but has the wrong top-level shape for the mapping.","triggerScenarios":"Loading an entity whose json aggregate column contains an array or a scalar instead of an object - e.g., the attribute was changed from List<Embeddable> to a single Embeddable (or data was written by another writer) without migrating the column.","commonSituations":"Changing an attribute between a plural JSON type and a single aggregate embeddable; other applications seeding the column with arrays; test fixtures inserting raw scalars.","solutions":["If the data really is an array, remap the attribute as a plural JSON type (@JdbcTypeCode(SqlTypes.JSON) on List<T>) so the array path (deserializeArray) is used.","If the mapping should stay an embeddable, migrate the data to wrap the value in an object (e.g., {\"items\": [...]}) or replace arrays with objects."],"exampleFix":"// before: column holds [\"a\",\"b\"] but mapping expects an embeddable object\n@JdbcTypeCode(SqlTypes.JSON)\n@Embedded Attributes attrs; // load -> Malformed JSON. Expected object but got: ARRAY_START\n\n// after: map the plural data as a list\n@JdbcTypeCode(SqlTypes.JSON)\nList<String> attrs;\n// or wrap in an object and keep an @Embeddable Attributes { List<String> items; }","handlingStrategy":"validation","validationCode":"// Validate the top-level shape before the entity load (Jackson example)\nstatic void assertTopLevelObject(String json) {\n    com.fasterxml.jackson.databind.JsonNode n;\n    try { n = new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); }\n    catch (Exception e) { throw new IllegalArgumentException(\"Invalid JSON\", e); }\n    if (!n.isObject()) {\n        throw new IllegalArgumentException(\"Expected a JSON object for embeddable mapping, got: \" + n.getNodeType());\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return session.find(Product.class, id);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Malformed JSON. Expected object\")) {\n        // column holds an array/scalar where the embeddable needs an object: fix mapping or data\n    } else {\n        throw e;\n    }\n}","preventionTips":["Keep singular/plural JSON attributes consistent with the stored shape across refactors","Add migration checks that verify top-level JSON shape per column","Write JSON columns only through the owning application"],"tags":["hibernate","json","malformed-data","aggregate-mapping","type-mismatch"],"backgroundTag":"malformed-json-data","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}