{"record":{"id":"69b2a64bfc10e7d6","repo":"Tencent/APIJSON","slug":"put-boolean-string-number","errorCode":null,"errorMessage":"PUT {}, {} 类型为 {}，不支持 Boolean, String, Number 等类型字段使用 'key+': [] 或 'key-': [] ！对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种！值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] ！","messagePattern":"PUT (.+?), (.+?) 类型为 (.+?)，不支持 Boolean, String, Number 等类型字段使用 'key\\+': \\[\\] 或 'key-': \\[\\] ！对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种！值为 JSONRequest 类型时传参必须是 'key\\+': \\[(.+?)\\] 或 'key-': \\['key', 'key2'\\] ！","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java","lineNumber":721,"sourceCode":"\n\n\t\t//add all 或 remove all <<<<<<<<<<<<<<<<<<<<<<<<<\n\t\tObject target = rp == null ? null : rp.get(realKey);\n\t\tif (target instanceof String) {\n\t\t\ttry {\n\t\t\t\ttarget = JSON.parse(target);\n\t\t\t} catch (Throwable e) {\n\t\t\t\tif (Log.DEBUG) {\n\t\t\t\t\tLog.e(TAG, \"try {\\n\" +\n\t\t\t\t\t\t\t\"\\t\\t\\t\\ttarget = parseJSON((String) target);\\n\" +\n\t\t\t\t\t\t\t\"\\t\\t\\t}\\n\" +\n\t\t\t\t\t\t\t\"\\t\\t\\tcatch (Throwable e) = \" + e.getMessage());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (apijson.JSON.isBoolOrNumOrStr(target)) {\n\t\t\tthrow new NullPointerException(\"PUT \" + path + \", \" + realKey + \" 类型为 \" + target.getClass().getSimpleName() + \"，\"\n\t\t\t\t\t+ \"不支持 Boolean, String, Number 等类型字段使用 'key+': [] 或 'key-': [] ！\"\n\t\t\t\t\t+ \"对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种！\"\n\t\t\t\t\t+ \"值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] ！\"\n\t\t\t);\n\t\t}\n\n\t\tboolean isAdd = putType == 1;\n\n\t\tCollection<Object> targetArray = target instanceof Collection ? (Collection<Object>) target : null;\n\t\tMap<String, ?> targetObj = target instanceof Map ? (Map<String, Object>) target : null;\n\n\t\tif (targetArray == null && targetObj == null) {\n\t\t\tif (isAdd == false) {\n\t\t\t\tthrow new NullPointerException(\"PUT \" + path + \", \" + realKey + (target == null ? \" 值为 null，不支持移除！\"\n\t\t\t\t\t\t: \" 类型为 \" + target.getClass().getSimpleName() + \"，不支持这样移除！\")\n\t\t\t\t\t\t+ \"对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种，且 key- 移除时，本身的值不能为 null！\"\n\t\t\t\t\t\t+ \"值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] ！\"\n\t\t\t\t);","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L703-L739","documentation":"For PUT-style incremental updates with 'key+': [...] / 'key-': [...], the current database-side value (target) is fetched and, after an attempted JSON.parse for strings, must be a JSONArray or JSONObject. If it is Boolean/String-that-isn't-JSON/Number, a NullPointerException is thrown: you cannot add/remove array elements on a scalar column.","triggerScenarios":"PUT request with \"tags+\": [\"a\"] where the column 'tags' currently holds true, 123, or a plain string like \"hello\" (not parseable as JSON array/object).","commonSituations":"Schema drift: the column was scalar (VARCHAR) and later APIJSON 'key+'/'key-' syntax is used against it; data written by another system as plain text; strings that fail JSON.parse fall through to isBoolOrNumOrStr.","solutions":["Store the column as JSON (JSONArray/JSONObject) before using 'key+'/'key-' — migrate the data: 'hello' -> \"[\\\"hello\\\"]\".","If the value is a JSON-encoded string, ensure it is valid JSON so JSON.parse succeeds before the check.","For plain scalar columns, use regular 'key': value assignment instead of '+'/'-' modifiers."],"exampleFix":"-- before: column tags = 'sport' (plain varchar)\n-- after: UPDATE \"User\" SET tags = '[\"sport\"]' WHERE id = 1;\n// then PUT { \"User\": { \"id\": 1, \"tags+\": [\"music\"] } } works","handlingStrategy":"type-guard","validationCode":"Object current = fetchColumnValue(tableName, id, key); // before composing the PUT\nif (current != null && !(current instanceof Collection || current instanceof Map)) {\n  throw new IllegalStateException(key + \" is scalar (\" + current.getClass().getSimpleName() + \"); key+/key- require a JSON column\");\n}","typeGuard":"function isJsonCollection(v: unknown): boolean {\n  if (typeof v === 'boolean' || typeof v === 'number' || v === null) return false;\n  if (typeof v === 'string') { try { const p = JSON.parse(v); return Array.isArray(p) || p !== null && typeof p === 'object'; } catch { return false; } }\n  return Array.isArray(v) || typeof v === 'object';\n}","tryCatchPattern":null,"preventionTips":["Migrate scalar columns to JSON ('[]'/'{}') before using key+/key-.","Fetch and inspect the current value type before composing incremental PUTs.","Use plain key:value for scalar columns."],"tags":["apijson","put","json-column","type-check","data-migration"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}