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

  1. Send @join as a single string: "&/User/id,</Moment/userId"
  2. Or as an object whose values are objects: {"&/User/id":{}}
  3. Never use a JSON array for @join
  4. 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

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


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/03e125c54ffacc82. Report an issue: GitHub.