{"record":{"id":"0f688238d3a5f436","repo":"Tencent/APIJSON","slug":"json-user","errorCode":null,"errorMessage":"JSON 对象格式不正确 ！正确示例例如 \"User\": {}","messagePattern":"JSON 对象格式不正确 ！正确示例例如 \"User\": (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractParser.java","lineNumber":2392,"sourceCode":"\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (hasTag == false) {\n\t\t\t\t\tobjAttrMap.put(KEY_TAG, isPost && isTableArray(objKey)\n\t\t\t\t\t\t\t? objKey.substring(0, objKey.length() - 2) + \":[]\" : objKey);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected M batchVerify(RequestMethod method, String tag, int version, String name, @NotNull M request, int maxUpdateCount, SQLCreator<T, M, L> creator) throws Exception {\n\t\tM correctRequest = JSON.createJSONObject();\n\t\tList<String> removeTmpKeys = new ArrayList<>(); // 请求json里面的临时变量,不需要带入后面的业务中,比如 @post、@get等\n\n\t\tSet<String> reqSet = request == null ? null : request.keySet();\n\t\tif (reqSet == null || request.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"JSON 对象格式不正确 ！正确示例例如 \\\"User\\\": {}\");\n\t\t}\n\n\t\t// 先收集所有显式方法，避免同一请求中方法指令的字段顺序影响对象解析结果。\n\t\tfor (String key : reqSet) {\n\t\t\tRequestMethod keyMethod = KEY_POST.equals(key) ? RequestMethod.POST : KEY_METHOD_ENUM_MAP.get(key);\n\t\t\tif (keyMethod == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tremoveTmpKeys.add(key);\n\t\t\ttry {\n\t\t\t\tparseMethodDirective(key, keyMethod, request);\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tLog.e(TAG, \"parse method directive failed\", e);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t}","sourceCodeStart":2374,"sourceCodeEnd":2410,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2374-L2410","documentation":"batchVerify() in AbstractParser rejects a batch request whose top-level JSON object is null or empty. A batch request must contain at least one table object such as \"User\": {} so the parser has something to verify and execute.","triggerScenarios":"POSTing {} or an empty body to a batch endpoint (e.g. /delete or /crud with batch semantics) that routes into batchVerify; client-side serialization bug that drops all keys before sending.","commonSituations":"Frontend builds the request from an empty selection (user ticked no rows); a fetch wrapper defaults to {} when the payload variable is undefined; gateway/proxy strips the body.","solutions":["Send at least one table object: {\"User\": {\"id\": 1}}","Guard client-side: skip the API call when the payload object has zero keys","Check network tab to confirm the body was not emptied by a serializer or interceptor"],"exampleFix":"// before\nPOST /delete  {}\n// after\nPOST /delete  {\"User\": {\"id\": 1}}","handlingStrategy":"validation","validationCode":"if (!req || Object.keys(req).length === 0) { throw new Error('batch request must contain at least one table object, e.g. {\"User\": {}}'); }","typeGuard":"const isNonEmptyObject = o => o != null && typeof o === 'object' && !Array.isArray(o) && Object.keys(o).length > 0;","tryCatchPattern":"try { await client.delete(req); } catch (e) { if (e.message.includes('JSON 对象格式不正确')) alert('请选择至少一条记录'); else throw e; }","preventionTips":["Disable the submit button when the selection is empty","Default the payload to a minimal {Table:{}} shape in the builder"],"tags":["apijson","request-validation","empty-body"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}