{"record":{"id":"0d6066556edd75ec","repo":"Tencent/APIJSON","slug":"post-table-key-value","errorCode":null,"errorMessage":"POST 请求必须在Table内设置要保存的 key:value ！","messagePattern":"POST 请求必须在Table内设置要保存的 key:value ！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":2380,"sourceCode":"\t\t\t\t\t\treturn StringUtil.isEmpty(group, true) ? \"1\" : \"count(DISTINCT \" + group + \")\";\n\t\t\t\t\t}\n\n\t\t\t\t\tString[] args = start == end - 1 ? null : StringUtil.split(c0.substring(start + 1, end));\n\t\t\t\t\tif (args != null && args.length > 0) {\n\t\t\t\t\t\tList<String> raw = getRaw();\n\t\t\t\t\t\tboolean containRaw = raw != null && raw.contains(KEY_COLUMN);\n\t\t\t\t\t\tc0 = parseSQLExpression(KEY_COLUMN, c0, containRaw, false, null);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn \"count(\" + c0 + \")\" + as + q + JSONResponse.KEY_COUNT + q;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn \"count(\" + (onlyOne ? gainKey(c0) : \"*\") + \")\" + as + q + JSONResponse.KEY_COUNT + q;\n\t\t\t//\t\t\treturn SQL.count(onlyOne && StringUtil.isName(column.get(0)) ? getKey(column.get(0)) : \"*\");\n\t\tcase POST:\n\t\t\tif (column == null || column.isEmpty()) {\n\t\t\t\tthrow new IllegalArgumentException(\"POST 请求必须在Table内设置要保存的 key:value ！\");\n\t\t\t}\n\n\t\t\tString s = \"\";\n\t\t\tboolean pfirst = true;\n\t\t\tfor (String c : column) {\n\t\t\t\tif (isPrepared() && StringUtil.isName(c) == false) {\n\t\t\t\t\t// 不能通过 ? 来代替，SELECT 'id','name' 返回的就是 id:\"id\", name:\"name\"，而不是数据库里的值！\n\t\t\t\t\tthrow new IllegalArgumentException(\"POST请求: 每一个 key:value 中的key都必须是1个单词！\");\n\t\t\t\t}\n\t\t\t\ts += ((pfirst ? \"\" : \",\") + gainKey(c));\n\n\t\t\t\tpfirst = false;\n\t\t\t}\n\n\t\t\treturn \"(\" + s + \")\";\n\t\tcase GET:\n\t\tcase GETS:\n\t\t\tString joinColumn = \"\";","sourceCodeStart":2362,"sourceCodeEnd":2398,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2362-L2398","documentation":"Thrown on POST requests in gainColumnString when the table object has no column list at all — i.e. the request body's table object contains no key:value pairs to save. POST generates an INSERT column list from the table object's keys, so an empty object leaves nothing to build and the request is rejected.","triggerScenarios":"POST /post/User with body {\"User\":{}} or {\"User\":{\"@explain\":true}} where the only keys are @-prefixed operator keys (which never become columns). Also when a client serializes an empty form/model to JSON and posts it unchanged.","commonSituations":"Submitting an empty form because all input fields were optional and left blank; accidentally wrapping values one level too deep (e.g. {\"User\":{\"User\":{...}}}) so the outer table object is empty; test scripts posting a placeholder object.","solutions":["Add at least one real column to the table object, e.g. {\"User\":{\"name\":\"aapi\"}}.","Check client code is not stripping all fields before POST — log the actual request body.","Ensure @-prefixed operator keys are not the only keys; they do not count as savable columns.","If you intend to query rather than insert, use GET/GETS instead of POST."],"exampleFix":"// before\nPOST /post/User  {\"User\":{}}\n// after\nPOST /post/User  {\"User\":{\"name\":\"apijson\",\"sex\":1}}","handlingStrategy":"validation","validationCode":"const cols = Object.keys(table || {}).filter(k => !k.startsWith('@'));\nif (cols.length === 0) throw new Error('POST needs at least one key:value in the table object');","typeGuard":"null","tryCatchPattern":"catch IllegalArgumentException on POST; show 'nothing to save' and re-prompt user","preventionTips":["Disable the submit button until at least one field is set","Log outbound POST bodies in dev builds to catch empty objects","Remember @-keys are operators, not savable columns"],"tags":["apijson","sql","input-validation","post-request","insert"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}