Tencent/APIJSON · error · IllegalArgumentException

{}/{}:value 中 value 必须为函数String!

Error message

{}/{}:value 中 value 必须为函数String!

What it means

Any key ending in '()' designates a remote function call and its value must be a String in the form function(key0,key1,...). This IllegalArgumentException fires when the value is not a String — e.g. a JSONObject, JSONArray, number or boolean.

Source

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

//						Log.d(TAG, "onParse  isTable(table) == false >> return true;");
//						return true;//舍去,对Table无影响
//					}
//				}

				// 直接替换原来的 key@: path 为 key: target
				Log.i(TAG, "onParse    >>  key = replaceKey; value = target;");
				key = replaceKey;
				value = target;
				Log.d(TAG, "onParse key = " + key + "; value = " + value);
			}
			else {
				throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为 依赖路径String 或 SQL子查询JSONObject !");
			}
		}

		if (key.endsWith("()")) {
			if (value instanceof String == false) {
				throw new IllegalArgumentException(path + "/" + key + ":value 中 value 必须为函数String!");
			}

			String k = key.substring(0, key.length() - 2);

			String type; //远程函数比较少用,一般一个Table:{}内用到也就一两个,所以这里用 "-","0","+" 更直观,转用 -1,0,1 对性能提升不大。
			boolean isMinus = k.endsWith("-");
            boolean isPlus = isMinus == false && k.endsWith("+");
			if (isMinus) { //不能封装到functionMap后批量执行,否则会导致非Table内的 key-():function() 在onChildParse后执行!
				type = "-";
				k = k.substring(0, k.length() - 1);
			}
			else if (isPlus) {
				type = "+";
				k = k.substring(0, k.length() - 1);
			}
			else {
				type = "0";
			}

View on GitHub (pinned to 5284052872)

Solutions

  1. Provide the value as a String: "key()": "functionName(argKey)".
  2. Keep arguments as request keys referenced inside the parentheses, not as nested JSON.

Example fix

// before
"tagList()": { "getTags": "id" }
// after
"tagList()": "getTags(id)"
Defensive patterns

Strategy: type-guard

Validate before calling

for (String k : request.keySet()) {
  String base = k.endsWith("()") ? k : (k.endsWith("-()") || k.endsWith("+()")) ? k.substring(0, k.length() - 3) + "()" : null;
  if (base != null && !(request.get(k) instanceof String)) throw new IllegalArgumentException(k + " must map to a function String");
}

Type guard

function isFunctionStringValue(key: string, v: unknown): boolean {
  return !/^(.*[-+])?\(\)$/.test(key) || typeof v === 'string';
}

Prevention

When it happens

Trigger: "name()": { "fun": "arg" } or "name()": 123. Any 'key()' entry whose value fails instanceof String, including 'key-()' / 'key+()' variants since the check runs after the suffix marker is stripped.

Common situations: Client builds the function call as structured JSON instead of a string; copy-paste replaces the quotes; confusion between 'key@' object form and 'key()' string form.

Related errors


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