{"record":{"id":"e5dd1a0c2ca141a3","repo":"Anuken/Mindustry","slug":"expecting-an-object-but-found-jsonmap","errorCode":null,"errorMessage":"Expecting an object, but found: '${jsonMap}'","messagePattern":"Expecting an object, but found: '(.+?)'","errorType":"validation","errorClass":"SerializationException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":1269,"sourceCode":"\n                if(!field.field.isAnnotationPresent(Nullable.class) && field.field.get(object) == null && !implicitNullable.contains(field.field.getType())){\n                    throw new RuntimeException(\"'\" + field.field.getName() + \"' in \" +\n                        ((object.getClass().isAnonymousClass() ? object.getClass().getSuperclass() : object.getClass()).getSimpleName()) +\n                        \" is missing! \" + object + \".\" + field.field.getName() + \" cannot be null.\");\n                }\n            }catch(Exception e){\n                throw new RuntimeException(e);\n            }\n        });\n    }\n\n    private void readFields(Object object, JsonValue jsonMap, boolean stripType){\n        if(stripType) jsonMap.remove(\"type\");\n        readFields(object, jsonMap);\n    }\n\n    void readFields(Object object, JsonValue jsonMap){\n        if(!jsonMap.isObject()) throw new SerializationException(\"Expecting an object, but found: '\" + jsonMap + \"'\");\n        JsonValue research = jsonMap.remove(\"research\");\n\n        toBeParsed.remove(object);\n        var type = object.getClass();\n        var fields = parser.getFields(type);\n        for(JsonValue child = jsonMap.child; child != null; child = child.next){\n            FieldMetadata metadata = fields.get(child.name().replace(\" \", \"_\"));\n            if(metadata == null){\n                if(ignoreUnknownFields){\n                    warn(\"@Unknown field '@' for class '@'\", currentContent == null ? \"\" : \"[\" + currentContent.minfo.sourceFile.name() + \"]: \", child.name, type.getSimpleName());\n                    continue;\n                }else{\n                    SerializationException ex = new SerializationException(\"Field not found: \" + child.name + \" (\" + type.getName() + \")\");\n                    ex.addTrace(child.trace());\n                    throw ex;\n                }\n            }\n            Field field = metadata.field;","sourceCodeStart":1251,"sourceCodeEnd":1287,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L1251-L1287","documentation":"ContentParser.readFields expects a JSON object (a map of name/value pairs) so it can map each child onto a reflective field of the target object. If the supplied JsonValue is an array, string, number, or bool, it cannot be iterated as fields and a SerializationException is thrown.","triggerScenarios":"A mod JSON value that must be an object is instead an array or scalar — e.g. a block definition whose body is a list, or a nested content field resolved to a primitive. Reached whenever readFields(object, jsonMap) is called with a non-object JsonValue.","commonSituations":"Wrong JSON structure (array where object expected); copy-paste from a list-style example; inline content defined with [] instead of {}; a 'type' resolution that produced a non-object value.","solutions":["Inspect the reported jsonMap value and confirm the surrounding field expects an object.","Rewrite the JSON node as an object literal { ... }.","Check the field type in the target class — if it expects a collection, the object-vs-array shape may be inverted.","Enable ignoreUnknownFields/logging to see which parent field led here."],"exampleFix":"// before (array where object expected)\n\"requirements\": [ [\"copper\", 10] ]\n\n// after (object form the parser expects)\n\"requirements\": { \"copper\": 10 }","handlingStrategy":"validation","validationCode":"// Confirm a JsonValue is an object before reading fields.\nif(jsonMap == null || !jsonMap.isObject()) {\n    throw new IllegalArgumentException(\"Expected JSON object, got: \" + (jsonMap == null ? \"null\" : jsonMap.type()));\n}","typeGuard":"boolean isJsonObject(JsonValue v){ return v != null && v.isObject(); }","tryCatchPattern":"try {\n    parser.readFields(obj, jsonMap);\n} catch(SerializationException e) {\n    if(e.getMessage().startsWith(\"Expecting an object\")) { /* fix JSON shape */ }\n    else throw e;\n}","preventionTips":["Author nested content as objects ({}) unless a field explicitly expects an array.","Lint mod JSON with a validator before loading.","Cross-check each field's expected shape against the source class."],"tags":["modding","content-parsing","json","serialization"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}