Tencent/APIJSON · error · IllegalArgumentException

{}:value 中 value 不合法!比较运算 [>, <, >=, <=] 只支持 [Boolean, Numbe

Error message

{}:value 中 value 不合法!比较运算 [>, <, >=, <=] 只支持 [Boolean, Number, String] 内的类型 !

What it means

Thrown by gainCompareString when the value used with a comparison operator key (key>, key<, key>=, key<=) is not a Boolean, Number, or String and not a Subquery. Comparison operators need an orderable scalar; arrays/objects are rejected before SQL generation.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:4053

		boolean not = column.endsWith("!"); // & | 没有任何意义,写法多了不好控制
		if (not) {
			column = column.substring(0, column.length() - 1);
		}

		String rc = column.endsWith("[") || column.endsWith("{") ? column.substring(0, column.length() - 1) : column;
		if (StringUtil.isName(rc) == false) {
			throw new IllegalArgumentException(key + ":value 中key不合法!不支持 ! 以外的逻辑符 !");
		}

		String logic = value == null && rawSQL == null ? (not ? SQL.IS_NOT : SQL.IS) : (not ? " != " : " = ");
		return gainKey(column) + logic + (value instanceof Subquery ? gainSubqueryString((Subquery<T, M, L>) value)
				: (rawSQL != null ? rawSQL : gainValue(key, column, value)));
	}

	public String gainCompareString(String key, String column, Object value, String type, String rawSQL) throws Exception {
		if (value != null && JSON.isBoolOrNumOrStr(value) == false && value instanceof Subquery == false) {
			throw new IllegalArgumentException(key + ":value 中 value 不合法!比较运算 [>, <, >=, <=] 只支持 [Boolean, Number, String] 内的类型 !");
		}

		String rc = column.endsWith("[") || column.endsWith("{") ? column.substring(0, column.length() - 1) : column;
		if ( ! StringUtil.isName(rc)) {
			throw new IllegalArgumentException(key + ":value 中 key 不合法!比较运算 [>, <, >=, <=] 不支持 [&, !, |] 中任何逻辑运算符 !");
		}

		return gainKey(column) + " " + type + " " + (value instanceof Subquery ? gainSubqueryString((Subquery<T, M, L>) value)
				: (rawSQL != null ? rawSQL : gainValue(key, column, value)));
	}

	public String gainKey(@NotNull String key) {
		String lenFun = "";
		if (key.endsWith("[")) {
			lenFun = isSQLServer() || isKingBaseSQLServer() ? "datalength" : "length";
			key = key.substring(0, key.length() - 1);
		}
		else if (key.endsWith("{")) {

View on GitHub (pinned to 5284052872)

Solutions

  1. Send a single scalar for comparisons: "age>": 18 and "age<": 30 as two keys.
  2. Combine the two bounds with @combine "age> & age<" or rely on default AND.
  3. Serialize dates/timestamps to String or Number before sending.

Example fix

// before
{"User": {"age>": [18, 30]}}
// after
{"User": {"age>": 18, "age<": 30}}
Defensive patterns

Strategy: type-guard

Validate before calling

const isScalar = v => ['boolean','number','string'].includes(typeof v);
for (const [k, v] of Object.entries(tableObj)) {
  if (/(>|<)$/.test(k) && v != null && !isScalar(v)) throw new Error(`comparison key ${k} needs a scalar value`);
}

Type guard

function isOrderableScalar(v) { return typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean'; }

Prevention

When it happens

Trigger: Sending {"User": {"age>": [18, 30]}} or {"date>=": {"$stamp": 123}} — collection or map values against a comparison suffix.

Common situations: Trying to express a range by passing an array to '>' (should be two conditions combined with &); sending structured JSON where a timestamp string/number is expected.

Related errors


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