Tencent/APIJSON · error · UnsupportedOperationException

key[]:{} 只支持 GET, GETS 方法!其它方法不允许传 {}:{} 等这种 key[]:{} 格式!

Error message

key[]:{} 只支持 GET, GETS 方法!其它方法不允许传 {}:{} 等这种 key[]:{} 格式!

What it means

onArrayParse rejects key[]:{} array syntax when the effective method is not GET/GETS (with strict true, so HEAD-like variants are excluded). The inner @method override is resolved first; for a non-subquery array under POST/PUT/DELETE etc. it throws UnsupportedOperationException. The comment notes this blocks a privilege bypass via [] with @role ADMIN plus a tag.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractParser.java:1329

	 * @param request parentObject的value
	 * @param parentPath parentObject的路径
	 * @param name parentObject的key
	 * @param isSubquery 是否为子查询
	 * @param cache SQL 结果缓存
	 * @return
	 * @throws Exception
	 */
	@Override
	public L onArrayParse(M request, String parentPath, String name, boolean isSubquery, L cache) throws Exception {
		if (Log.DEBUG) {
			Log.i(TAG, "\n\n\n onArrayParse parentPath = " + parentPath
					+ "; name = " + name + "; request = " + JSON.toJSONString(request));
		}

		//不能允许GETS,否则会被通过"[]":{"@role":"ADMIN"},"Table":{},"tag":"Table"绕过权限并能批量查询
		RequestMethod _method = request.get(KEY_METHOD) == null ? requestMethod : RequestMethod.valueOf(getString(request, KEY_METHOD));
		if (isSubquery == false && RequestMethod.isGetMethod(_method, true) == false) {
			throw new UnsupportedOperationException("key[]:{} 只支持 GET, GETS 方法!其它方法不允许传 " + name + ":{} 等这种 key[]:{} 格式!");
		}
		if (request == null || request.isEmpty()) { // jsonKey-jsonValue 条件
			return null;
		}
		String path = getAbsPath(parentPath, name);


		//不能改变,因为后面可能继续用到,导致1以上都改变 []:{0:{Comment[]:{0:{Comment:{}},1:{...},...}},1:{...},...}
		final String query = getString(request, apijson.JSONRequest.KEY_QUERY);
		final Boolean compat = getBoolean(request, apijson.JSONRequest.KEY_COMPAT);
		final Integer count = getInteger(request, apijson.JSONRequest.KEY_COUNT); //TODO 如果不想用默认数量可以改成 getIntValue(apijson.JSONRequest.KEY_COUNT);
		final Integer page = getInteger(request, apijson.JSONRequest.KEY_PAGE);
		final Object join = request.get(apijson.JSONRequest.KEY_JOIN);

		int query2;
		if (query == null) {
			query2 = apijson.JSONRequest.QUERY_TABLE;
		}

View on GitHub (pinned to 5284052872)

Solutions

  1. For write operations use the batch format key:[] with an array VALUE (e.g. "User":[]), not the page-array key[]:{} syntax
  2. Change the HTTP method to GET (or GETS with tag) when you only want to query lists
  3. Remove inner @method overrides that set non-GET methods inside []:{}
  4. Keep pagination/list queries strictly read-only; do reads and writes in separate requests

Example fix

// before (POST + page-array)
POST /post {"[]":{"User":{...}}}
// after
POST /post {"User":[{...},{...}]}
Defensive patterns

Strategy: validation

Validate before calling

if (method != GET && bodyHasPageArraySyntax(body)) throw new IllegalArgumentException("page-array [] not allowed for " + method);

Type guard

boolean isPageArrayRequest(Object key) { return key instanceof String && ((String) key).endsWith("[]"); }

Prevention

When it happens

Trigger: Sending e.g. {"[]":{...},"tag":"X"} with requestMethod=POST, or an array whose inner "@method":"PUT" (only GET/GETS accepted). Subqueries (@from joins) are exempt because isSubquery=true.

Common situations: Copy-pasting a GET list query into a POST batch; trying to batch-modify by wrapping objects in an array; frontend reuses the list endpoint's body for a save call; older versions permitted it and an upgrade enforces the rule.

Related errors


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