{"record":{"id":"78a590fda035484b","repo":"Tencent/APIJSON","slug":"value-value-bool","errorCode":null,"errorMessage":"{}:value 中 value 不合法！比较运算 [>, <, >=, <=] 只支持 [Boolean, Number, String] 内的类型 ！","messagePattern":"(.+?):value 中 value 不合法！比较运算 \\[>, <, >=, <=\\] 只支持 \\[Boolean, Number, String\\] 内的类型 ！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":4053,"sourceCode":"\n\t\tboolean not = column.endsWith(\"!\"); // & | 没有任何意义，写法多了不好控制\n\t\tif (not) {\n\t\t\tcolumn = column.substring(0, column.length() - 1);\n\t\t}\n\n\t\tString rc = column.endsWith(\"[\") || column.endsWith(\"{\") ? column.substring(0, column.length() - 1) : column;\n\t\tif (StringUtil.isName(rc) == false) {\n\t\t\tthrow new IllegalArgumentException(key + \":value 中key不合法！不支持 ! 以外的逻辑符 ！\");\n\t\t}\n\n\t\tString logic = value == null && rawSQL == null ? (not ? SQL.IS_NOT : SQL.IS) : (not ? \" != \" : \" = \");\n\t\treturn gainKey(column) + logic + (value instanceof Subquery ? gainSubqueryString((Subquery<T, M, L>) value)\n\t\t\t\t: (rawSQL != null ? rawSQL : gainValue(key, column, value)));\n\t}\n\n\tpublic String gainCompareString(String key, String column, Object value, String type, String rawSQL) throws Exception {\n\t\tif (value != null && JSON.isBoolOrNumOrStr(value) == false && value instanceof Subquery == false) {\n\t\t\tthrow new IllegalArgumentException(key + \":value 中 value 不合法！比较运算 [>, <, >=, <=] 只支持 [Boolean, Number, String] 内的类型 ！\");\n\t\t}\n\n\t\tString rc = column.endsWith(\"[\") || column.endsWith(\"{\") ? column.substring(0, column.length() - 1) : column;\n\t\tif ( ! StringUtil.isName(rc)) {\n\t\t\tthrow new IllegalArgumentException(key + \":value 中 key 不合法！比较运算 [>, <, >=, <=] 不支持 [&, !, |] 中任何逻辑运算符 ！\");\n\t\t}\n\n\t\treturn gainKey(column) + \" \" + type + \" \" + (value instanceof Subquery ? gainSubqueryString((Subquery<T, M, L>) value)\n\t\t\t\t: (rawSQL != null ? rawSQL : gainValue(key, column, value)));\n\t}\n\n\tpublic String gainKey(@NotNull String key) {\n\t\tString lenFun = \"\";\n\t\tif (key.endsWith(\"[\")) {\n\t\t\tlenFun = isSQLServer() || isKingBaseSQLServer() ? \"datalength\" : \"length\";\n\t\t\tkey = key.substring(0, key.length() - 1);\n\t\t}\n\t\telse if (key.endsWith(\"{\")) {","sourceCodeStart":4035,"sourceCodeEnd":4071,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4035-L4071","documentation":"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.","triggerScenarios":"Sending {\"User\": {\"age>\": [18, 30]}} or {\"date>=\": {\"$stamp\": 123}} — collection or map values against a comparison suffix.","commonSituations":"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.","solutions":["Send a single scalar for comparisons: \"age>\": 18 and \"age<\": 30 as two keys.","Combine the two bounds with @combine \"age> & age<\" or rely on default AND.","Serialize dates/timestamps to String or Number before sending."],"exampleFix":"// before\n{\"User\": {\"age>\": [18, 30]}}\n// after\n{\"User\": {\"age>\": 18, \"age<\": 30}}","handlingStrategy":"type-guard","validationCode":"const isScalar = v => ['boolean','number','string'].includes(typeof v);\nfor (const [k, v] of Object.entries(tableObj)) {\n  if (/(>|<)$/.test(k) && v != null && !isScalar(v)) throw new Error(`comparison key ${k} needs a scalar value`);\n}","typeGuard":"function isOrderableScalar(v) { return typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean'; }","tryCatchPattern":null,"preventionTips":["Send one bound per comparison key; combine ranges with two keys.","Serialize dates to ISO strings or numbers before sending."],"tags":["apijson","value-type","compare","validation"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}