{"record":{"id":"ee0a7d1f0d03ef78","repo":"Tencent/APIJSON","slug":"put-null-jsonarray","errorCode":null,"errorMessage":"PUT {}, {} 值为 null，不支持移除！对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种，且 key- 移除时，本身的值不能为 null！值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] ！","messagePattern":"PUT (.+?), (.+?) 值为 null，不支持移除！对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种，且 key- 移除时，本身的值不能为 null！值为 JSONRequest 类型时传参必须是 'key\\+': \\[(.+?)\\] 或 'key-': \\['key', 'key2'\\] ！","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java","lineNumber":735,"sourceCode":"\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);\n\t\t\t}\n\n\t\t\ttargetArray = JSON.createJSONArray();\n\t\t}\n\n\t\tfor (int i = 0; i < array.size(); i++) {\n\t\t\tObject obj = array.get(i);\n\t\t\tif (obj == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isAdd) {\n\t\t\t\tif (targetArray != null) {\n\t\t\t\t\tif (targetArray.contains(obj)) {","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L717-L753","documentation":"PUT variant of the null-target error: when using 'key-': [...] to remove items and the current value (target) is null — or a non-collection/non-map type after the earlier check — removal is impossible. The database value must be JSONArray or JSONObject, and a null value cannot be 'removed from', hence NullPointerException with guidance on the expected forms.","triggerScenarios":"PUT { \"User\": { \"id\": 1, \"tags-\": [\"a\"] } } where the row's tags column is NULL (never set), so target == null and isAdd == false.","commonSituations":"Removing from an optional JSON column that was never initialized; rows created before the column was added; test fixtures that insert NULL.","solutions":["Initialize the column to an empty JSON array/object ('[]' or '{}') for existing rows before issuing key- updates.","Client-side: skip the key- operation (or send an empty removal list) when the current value is known to be null.","If semantics allow, treat null as empty by first writing 'key': [] then applying removals in a second request."],"exampleFix":"-- before: tags IS NULL, request { \"tags-\": [\"a\"] } -> error\n-- after: UPDATE \"User\" SET tags = '[]' WHERE id = 1;\n// then the key- request succeeds (or is a no-op)","handlingStrategy":"validation","validationCode":"Object current = fetchColumnValue(tableName, id, key);\nif (current == null) {\n  if (removalRequested) throw new IllegalStateException(key + \" is null; initialize it to [] or {} before key- operations\");\n}","typeGuard":"function canRemoveFrom(v: unknown): boolean {\n  return v !== null && (Array.isArray(v) || typeof v === 'object');\n}","tryCatchPattern":null,"preventionTips":["Initialize JSON columns to '[]'/'{}' at row creation.","Backfill NULLs before enabling key- in clients.","Skip key- requests when the known current value is null."],"tags":["apijson","put","null-value","json-column","data-migration"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}