Tencent/APIJSON · error · NullPointerException

PUT {}, {} 值为 null,不支持移除!对应字段在数据库的值必须为 JSONArray, JSONObject

Error message

PUT {}, {} 值为 null,不支持移除!对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种,且 key- 移除时,本身的值不能为 null!值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] !

What it means

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.

Source

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

			}
		}

		if (apijson.JSON.isBoolOrNumOrStr(target)) {
			throw new NullPointerException("PUT " + path + ", " + realKey + " 类型为 " + target.getClass().getSimpleName() + ","
					+ "不支持 Boolean, String, Number 等类型字段使用 'key+': [] 或 'key-': [] !"
					+ "对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种!"
					+ "值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] !"
			);
		}

		boolean isAdd = putType == 1;

		Collection<Object> targetArray = target instanceof Collection ? (Collection<Object>) target : null;
		Map<String, ?> targetObj = target instanceof Map ? (Map<String, Object>) target : null;

		if (targetArray == null && targetObj == null) {
			if (isAdd == false) {
				throw new NullPointerException("PUT " + path + ", " + realKey + (target == null ? " 值为 null,不支持移除!"
						: " 类型为 " + target.getClass().getSimpleName() + ",不支持这样移除!")
						+ "对应字段在数据库的值必须为 JSONArray, JSONObject 中的一种,且 key- 移除时,本身的值不能为 null!"
						+ "值为 JSONRequest 类型时传参必须是 'key+': [{'key': value, 'key2': value2}] 或 'key-': ['key', 'key2'] !"
				);
			}

			targetArray = JSON.createJSONArray();
		}

		for (int i = 0; i < array.size(); i++) {
			Object obj = array.get(i);
			if (obj == null) {
				continue;
			}

			if (isAdd) {
				if (targetArray != null) {
					if (targetArray.contains(obj)) {

View on GitHub (pinned to 5284052872)

Solutions

  1. Initialize the column to an empty JSON array/object ('[]' or '{}') for existing rows before issuing key- updates.
  2. Client-side: skip the key- operation (or send an empty removal list) when the current value is known to be null.
  3. If semantics allow, treat null as empty by first writing 'key': [] then applying removals in a second request.

Example fix

-- before: tags IS NULL, request { "tags-": ["a"] } -> error
-- after: UPDATE "User" SET tags = '[]' WHERE id = 1;
// then the key- request succeeds (or is a no-op)
Defensive patterns

Strategy: validation

Validate before calling

Object current = fetchColumnValue(tableName, id, key);
if (current == null) {
  if (removalRequested) throw new IllegalStateException(key + " is null; initialize it to [] or {} before key- operations");
}

Type guard

function canRemoveFrom(v: unknown): boolean {
  return v !== null && (Array.isArray(v) || typeof v === 'object');
}

Prevention

When it happens

Trigger: PUT { "User": { "id": 1, "tags-": ["a"] } } where the row's tags column is NULL (never set), so target == null and isAdd == false.

Common situations: Removing from an optional JSON column that was never initialized; rows created before the column was added; test fixtures that insert NULL.

Related errors


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