{"record":{"id":"034e06443ee1a7c4","repo":"Tencent/APIJSON","slug":"e-getkey-targettable-targetalias-targetkey","errorCode":null,"errorMessage":"${e.getKey()}:'/targetTable:targetAlias/targetKey' 中 targetAlias 值 ${targetAlias} 不合法！必须满足英文单词变量名格式！","messagePattern":"(.+?):'/targetTable:targetAlias/targetKey' 中 targetAlias 值 (.+?) 不合法！必须满足英文单词变量名格式！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractParser.java","lineNumber":1835,"sourceCode":"\t\t\t\tString targetKey = index < 0 ? null : targetPath.substring(index + 1);\n\t\t\t\tif (StringUtil.isName(targetKey) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中 targetKey 值 \" + targetKey + \" 不合法！必须满足英文单词变量名格式！\");\n\t\t\t\t}\n\n\t\t\t\ttargetPath = targetPath.substring(0, index);\n\t\t\t\tindex = targetPath.lastIndexOf(\"/\");\n\t\t\t\tString targetTableKey = index < 0 ? targetPath : targetPath.substring(index + 1);\n\n\t\t\t\t// 主表允许别名\n\t\t\t\tapijson.orm.Entry<String, String> targetEntry = Pair.parseEntry(targetTableKey, true);\n\t\t\t\tString targetTable = targetEntry.getKey(); //User\n\t\t\t\tif (StringUtil.isName(targetTable) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中 targetTable 值 \" + targetTable + \" 不合法！必须满足大写字母开头的表对象英文单词 key 格式！\");\n\t\t\t\t}\n\n\t\t\t\tString targetAlias = targetEntry.getValue(); //owner\n\t\t\t\tif (StringUtil.isNotEmpty(targetAlias, true) && StringUtil.isName(targetAlias) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable:targetAlias/targetKey' 中 targetAlias 值 \" + targetAlias + \" 不合法！必须满足英文单词变量名格式！\");\n\t\t\t\t}\n\n\t\t\t\t//targetTable = targetTableKey;  // 主表允许别名\n\t\t\t\tif (StringUtil.isName(targetTable) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中 targetTable 值 \" + targetTable + \" 不合法！必须满足大写字母开头的表对象英文单词 key 格式！\");\n\t\t\t\t}\n\n\t\t\t\t//对引用的JSONObject添加条件\n\t\t\t\tMap<String, Object> targetObj;\n\t\t\t\ttry {\n\t\t\t\t\ttargetObj = JSON.get(request, targetTableKey);\n\t\t\t\t}\n\t\t\t\tcatch (Exception e2) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中路径对应的 '\" + targetTableKey + \"':value 中 value 类型不合法！必须是 {} 这种 Map<String, Object> 格式！\" + e2.getMessage());\n\t\t\t\t}\n\n\t\t\t\tif (targetObj == null) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中路径对应的对象 '\" + targetTableKey + \"':{} 不存在或值为 null ！必须是 {} 这种 Map<String, Object> 格式！\");","sourceCodeStart":1817,"sourceCodeEnd":1853,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1817-L1853","documentation":"A reference path may address a table through an alias ('/targetTable:targetAlias/targetKey'). The alias part is optional, but if present it must satisfy StringUtil.isName. This IllegalArgumentException fires when a non-empty alias contains invalid identifier characters.","triggerScenarios":"'userId@': '/User:my user/id' (space), '/User:u-1/id' (hyphen), '/User:1owner/id' (starts with digit), '/User:owner:extra/id' (double colon).","commonSituations":"Using display labels or SQL expressions as alias; alias values generated from user input or i18n strings; misunderstanding that ':' separates exactly one table:alias pair.","solutions":["Change the alias to a plain identifier: '/User:owner/id'","Drop the alias if the default (table-name) reference is sufficient: '/User/id'"],"exampleFix":"// before\n{ 'join': '</Comment', 'Comment': { 'userId@': '/User:my user/id' } }\n// after\n{ 'join': '</Comment', 'Comment': { 'userId@': '/User:owner/id' } }","handlingStrategy":"validation","validationCode":"const NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\nfunction checkRefAliases(req) {\n  for (const tbl of Object.values(req)) {\n    if (tbl && typeof tbl === 'object') {\n      for (const [k, v] of Object.entries(tbl)) {\n        if (!k.endsWith('@') || typeof v !== 'string') continue;\n        const seg = v.split('/')[1];\n        const alias = seg.includes(':') ? seg.split(':')[1] : null;\n        if (alias != null && alias !== '' && !NAME_RE.test(alias)) return `${k}: alias '${alias}' is not a valid identifier`;\n      }\n    }\n  }\n  return null;\n}","typeGuard":"const isValidAlias = (a) => a == null || /^[A-Za-z_][A-Za-z0-9_]*$/.test(a);","tryCatchPattern":"Catch IllegalArgumentException containing 'targetAlias 值'; replace the alias with a plain identifier or drop it.","preventionTips":["Aliases in reference paths are plain identifiers — no spaces, hyphens, digits-first, or extra ':'","Reuse the same alias everywhere: join path, table object key, and ON reference path"],"tags":["apijson","join","alias","identifier"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}