Tencent/APIJSON · error · IllegalArgumentException

{}/{}:{} 不合法!数组 []:{} 中第一个 key:{} 必须是主表 TableKey:{} !不能为 arr

Error message

{}/{}:{} 不合法!数组 []:{} 中第一个 key:{} 必须是主表 TableKey:{} !不能为 arrayKey[]:{} !

What it means

Inside an array request '[]':{}, the first entry (index 0, the main table position when type == TYPE_ITEM) must be a table key 'TableKey':{}, not another array 'arrayKey[]':{}. onChildParse throws this when the very first child parsed for an array item is itself an array key, because the array's item template has no main table to anchor the query.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java:604

	/**
	 * @param index
	 * @param key
	 * @param value
	 * @param cache
	 * @return
	 * @throws Exception
	 */
	@Override
	public Object onChildParse(int index, String key, M value, Object cache) throws Exception {
		boolean isFirst = index <= 0;
		boolean isMain = isFirst && type == TYPE_ITEM;

		Object child;
		boolean isEmpty;

		if (JSONMap.isArrayKey(key)) { // APIJSON Array
			if (isMain) {
				throw new IllegalArgumentException(parentPath + "/" + key + ":{} 不合法!"
						+ "数组 []:{} 中第一个 key:{} 必须是主表 TableKey:{} !不能为 arrayKey[]:{} !");
			}

			if (arrayConfig == null || arrayConfig.getPosition() == 0) {
				arrayCount ++;
				int maxArrayCount = parser.getMaxArrayCount();
				if (arrayCount > maxArrayCount) {
					throw new IllegalArgumentException(path + " 内截至 " + key + ":{} 时数组对象 key[]:{} "
                            + "的数量达到 " + arrayCount + " 已超限,必须在 0-" + maxArrayCount + " 内 !");
				}
			}

			String query = getString(value, KEY_QUERY);
			child = parser.onArrayParse(value, path, key, isSubquery, cache instanceof List<?> ? (L) cache : null);
			isEmpty = child == null || ((List<?>) child).isEmpty();

			if ("2".equals(query) || "ALL".equals(query)) { // 不判断 isEmpty,因为分页数据可能只是某页没有
				String totalKey = JSONResponse.formatArrayKey(key) + "Total";

View on GitHub (pinned to 5284052872)

Solutions

  1. Put the main table object first inside '[]': "[]": { "User": {...}, "list[]": [...] }.
  2. Use an ordered map (JSONObject preserves order; avoid HashSet/unordered structures) when constructing requests programmatically.
  3. If no main table is intended, restructure so the nested array lives inside a table object rather than at array position 0.

Example fix

// before
"[]": { "Comment[]": { "Comment": {} }, "User": { "id": 1 } }
// after
"[]": { "User": { "id": 1 }, "Comment[]": { "Comment": {} } }
Defensive patterns

Strategy: validation

Validate before calling

// first entry inside "[]" must not be an array key
String firstKey = arrayRequest.keySet().iterator().next();
if (firstKey.endsWith("[]")) throw new IllegalArgumentException("first key inside [] must be a TableKey");

Type guard

function firstArrayChildIsTable(entries: [string, unknown][]): boolean {
  return !(entries[0]?.[0]?.endsWith('[]') ?? true);
}

Prevention

When it happens

Trigger: "[]": { "list[]": [1,2], "User": { ... } } — any request where the first key inside '[]' ends with '[]'. Only subsequent positions may nest arrays.

Common situations: Reordering keys so a nested array lands first; JSON serializers that don't preserve insertion order putting 'something[]' before the main table; building the request from a Map with non-deterministic ordering.

Related errors


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