Tencent/APIJSON · error · UnsupportedDataTypeException
AbstractParser.onJoinParse join 只能是 String 或 Map<String, Ob
Error message
AbstractParser.onJoinParse join 只能是 String 或 Map<String, Object> 类型!
What it means
The @join value may be a String ("&/Table0/key0,</Table1/key1") or a Map of such entries. onJoinParse type-checks it; any other JSON type (number, boolean, array) throws UnsupportedDataTypeException naming the two allowed types. null is tolerated (skipped).
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractParser.java:1561
* @throws Exception
*/
private List<Join<T, M, L>> onJoinParse(Object join, M request) throws Exception {
Map<String, Object> joinMap = null;
if (join instanceof Map<?, ?>) {
joinMap = (M) join;
}
else if (join instanceof String) {
String[] sArr = request == null || request.isEmpty() ? null : StringUtil.split((String) join);
if (sArr != null && sArr.length > 0) {
joinMap = new LinkedHashMap<String, Object>(); //注意:这里必须要保证join连接顺序,保证后边遍历是按照join参数的顺序生成的SQL
for (int i = 0; i < sArr.length; i++) {
joinMap.put(sArr[i], new LinkedHashMap<String, Object>());
}
}
}
else if (join != null){
throw new UnsupportedDataTypeException(TAG + ".onJoinParse join 只能是 String 或 Map<String, Object> 类型!");
}
List<Entry<String, Object>> slashKeys = new ArrayList<>();
List<Entry<String, Object>> nonSlashKeys = new ArrayList<>();
Set<Entry<String, Object>> entries = joinMap == null ? null : joinMap.entrySet();
if (entries == null || entries.isEmpty()) {
Log.e(TAG, "onJoinParse set == null || set.isEmpty() >> return null;");
return null;
}
for (Entry<String, Object> e : entries) {
String path = e.getKey();
if (path != null && path.indexOf("/") > 0) {
slashKeys.add(e); // 以 / 开头的 key,例如 </Table/key@
} else {
nonSlashKeys.add(e); // 普通 key,例如 Table: {}
}
}View on GitHub (pinned to 5284052872)
Solutions
- Send @join as a single string: "&/User/id,</Moment/userId"
- Or as an object whose values are objects: {"&/User/id":{}}
- Never use a JSON array for @join
- Validate the wire format in tests with a schema assertion
Example fix
// before
{"@join":["&/User/id"]}
// after
{"@join":"&/User/id"} Defensive patterns
Strategy: type-guard
Validate before calling
Object j = req.get("@join");
if (j != null && !(j instanceof String) && !(j instanceof Map)) throw new IllegalArgumentException("@join must be String or Map"); Type guard
boolean joinValueIsLegalType(Object join) {
return join == null || join instanceof String || join instanceof Map;
} Prevention
- Always emit @join as a single string
- Reject array-typed @join in request builders
- Add a schema test: @join type in [string, object]
When it happens
Trigger: "@join": ["&/User/id"] (array of strings), "@join": 123, "@join": true. Note a JSON array is NOT accepted even though it looks natural — only String or Object.
Common situations: Client builds join list as an array because that is idiomatic elsewhere; templating engines render a list where a string was expected; copy from docs that show the map form but serialize wrongly.
Related errors
- @join:value 中value不合法!必须为 &/Table0/key0,</Table1/key1,... 或
- @join:value 中 value 值 {} 不合法!必须为 &/Table0,</Table1/key1,@/Ta
- @join:'{}' 对应的 {} 不是合法的数组 key[] !@ APP JOIN 最多允许跨 1 层,只能是子数组
- @join:value 中 value 的 Table 值 {} 不合法!必须为 &/Table0,</Table1/k
- join:value 中 value 的 alias 值 ${alias} 不合法!必须为 &/Table0,</Tab
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/03e125c54ffacc82.
Report an issue: GitHub.