{"record":{"id":"c6b078c9502d5ff0","repo":"Tencent/APIJSON","slug":"join-value-value-alias-alias-ta","errorCode":null,"errorMessage":"join:value 中 value 的 alias 值 ${alias} 不合法！必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式！且 Table:alias 的 alias 必须满足英文单词变量名格式！","messagePattern":"join:value 中 value 的 alias 值 (.+?) 不合法！必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,\\.\\.\\. 或 (.+?), '</Table1/key1':(.+?),\\.\\.\\. \\} 这种格式！且 Table:alias 的 alias 必须满足英文单词变量名格式！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractParser.java","lineNumber":1646,"sourceCode":"\t\t\tString arrKey = index2 < 0 ? null : tableKey.substring(0, index2);\n\t\t\tif (arrKey != null && isArrayKey(arrKey) == false) {\n\t\t\t\tthrow new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + \":'\" + e.getKey() + \"' 对应的 \" + arrKey + \" 不是合法的数组 key[] ！\" +\n\t\t\t\t\t\t\"@ APP JOIN 最多允许跨 1 层，只能是子数组，且数组对象中不能有 join: value 键值对！\");\n\t\t\t}\n\n\t\t\ttableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);\n\n\t\t\tapijson.orm.Entry<String, String> entry = Pair.parseEntry(tableKey, true);\n\t\t\tString table = entry.getKey(); // User\n\t\t\tif (StringUtil.isName(table) == false) {\n\t\t\t\tthrow new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + \":value 中 value 的 Table 值 \" + table + \" 不合法！\"\n\t\t\t\t\t\t+ \"必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式！\"\n\t\t\t\t\t\t+ \"且 Table 必须满足大写字母开头的表对象英文单词 key 格式！\");\n\t\t\t}\n\n\t\t\tString alias = entry.getValue(); // owner\n\t\t\tif (StringUtil.isNotEmpty(alias, true) && StringUtil.isName(alias) == false) {\n\t\t\t\tthrow new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + \":value 中 value 的 alias 值 \" + alias + \" 不合法！\"\n\t\t\t\t\t\t+ \"必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式！\"\n\t\t\t\t\t\t+ \"且 Table:alias 的 alias 必须满足英文单词变量名格式！\");\n\t\t\t}\n\n\t\t\t// 取出Table对应的JSONObject，及内部引用赋值 key:value\n\t\t\tM tableObj;\n\t\t\tM parentPathObj;\t// 保留\n\t\t\ttry {\n\t\t\t\tparentPathObj = arrKey == null ? request : JSON.get(request, arrKey);\t// 保留\n\t\t\t\ttableObj = parentPathObj == null ? null : JSON.get(parentPathObj, tableKey);\n\t\t\t\tif (tableObj == null) {\n\t\t\t\t\tthrow new NullPointerException(\"tableObj == null\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (Exception e2) {\n\t\t\t\tthrow new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + \":'\" + e.getKey() + \"' 对应的 \" + tableKey + \":value 中 value 类型不合法！\" +\n          \t\t\t\"必须是 {} 这种 Map<String, Object> 格式！\" + e2.getMessage());\n\t\t\t}","sourceCodeStart":1628,"sourceCodeEnd":1664,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1628-L1664","documentation":"If a join path carries Table:alias, the alias is validated with StringUtil.isName (non-empty case): it must be a plain identifier word. An alias containing symbols, slashes, brackets, or starting with a digit throws IllegalArgumentException with the grammar reminder.","triggerScenarios":"\"@join\":\"&/User:owner-2\", '@/User:a.b', or '&/User:owner/toId' where the slash makes the alias segment parse into invalid parts. Any non-identifier alias text.","commonSituations":"Using quoted or spaced aliases; trying to express join ON-conditions in the alias slot; concatenating user input into the alias; thinking alias may include dots for schema qualification.","solutions":["Keep the alias a bare identifier: '&/User:owner'","Use the alias only for disambiguation between multiple joins of the same table","Put join conditions inside the table object, not in the alias","Sanitize any dynamic alias to [A-Za-z_][A-Za-z0-9_]* before sending"],"exampleFix":"// before\n{\"@join\":\"&/User:owner-2/id\"}\n// after\n{\"@join\":\"&/User:owner2/id\"}","handlingStrategy":"validation","validationCode":"if (alias != null && !alias.matches(\"^[A-Za-z_][A-Za-z0-9_]*$\")) throw new IllegalArgumentException(\"bad join alias: \" + alias);","typeGuard":"boolean isValidJoinAlias(String a) { return a == null || a.matches(\"^[A-Za-z_][A-Za-z0-9_]*$\"); }","tryCatchPattern":null,"preventionTips":["Keep aliases as bare identifiers","Sanitize dynamic aliases before embedding in join paths","Remember alias slot is for disambiguation only, not conditions"],"tags":["apijson","join","alias","identifier-validation"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}