Tencent/APIJSON · error · UnsupportedDataTypeException

{key}:value 的 value 不合法!类型必须是 OBJECT ,结构为 {} !

Error message

{key}:value 的 value 不合法!类型必须是 OBJECT ,结构为 {} !

What it means

Thrown during template-value merge in verify: the target (Request-table template) declares a key whose value is an OBJECT ({}), but the client sent a non-object (scalar or array) for the same key. The request structure must mirror the template structure.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java:1017

				if (key == null || OPERATION_KEY_LIST.contains(key)) {
					continue;
				}
                Object tvalue = entry.getValue();
                Object rvalue = real.get(key);
				if (rvalue != null && stringKeyList != null && stringKeyList.contains(key)) {
					rvalue = toJSONString(rvalue);
				}
				if (rvalue != null && trimKeyList != null && trimKeyList.contains(key)) {
					rvalue = StringUtil.trim(rvalue);
				}

				if (callback.onParse(key, tvalue, rvalue) == false) {
					continue;
				}

				if (tvalue instanceof Map<?, ?>) { // JSONRequest,往下一级提取
					if (rvalue != null && rvalue instanceof Map<?, ?> == false) {
						throw new UnsupportedDataTypeException(key + ":value 的 value 不合法!类型必须是 OBJECT ,结构为 {} !");
					}
					tvalue = callback.onParseJSONObject(key, (M) tvalue, (M) rvalue);

					objKeySet.add(key);
				} else if (tvalue instanceof List<?>) { // L
					if (rvalue != null && rvalue instanceof List<?> == false) {
						throw new UnsupportedDataTypeException(key + ":value 的 value 不合法!类型必须是 ARRAY ,结构为 [] !");
					}
					tvalue = callback.onParseJSONArray(key, (L) tvalue, (L) rvalue);

					if ((method == POST || method == PUT) && isArrayKey(key)) {
						objKeySet.add(key);
					}
				} else { // 其它Object
					tvalue = callback.onParseObject(key, tvalue, rvalue);
				}

				if (tvalue != null) { // 可以在target中加上一些不需要客户端传的键值对

View on GitHub (pinned to 5284052872)

Solutions

  1. Send the value as an object matching the template: {"address":{"city":"Beijing"}}
  2. If the scalar form is intended, change the Request-table template value to a scalar
  3. Version the endpoint and keep the old template for legacy clients

Example fix

// before
{"User":{"address":"Beijing"}}
// after
{"User":{"address":{"city":"Beijing"}}}
Defensive patterns

Strategy: type-guard

Validate before calling

// template: {address: {}} -> require object
function assertShape(value, template) {
  for (const k of Object.keys(template)) {
    const t = template[k], v = value[k];
    if (v != null && t != null && typeof t === 'object' && !Array.isArray(t) && typeof v !== 'object') {
      throw new TypeError(`${k} must be an object per template`);
    }
  }
}

Type guard

const matchesTemplateShape = (v, t) => t instanceof Object && !(t instanceof Array) ? (v == null || v instanceof Object && !(v instanceof Array)) : true;

Prevention

When it happens

Trigger: Template has "User":{"address":{}} but the client sends {"User":{"address":"Beijing"}} — rvalue is not a Map while tvalue is.

Common situations: API evolution: a field was promoted from scalar to nested object in the template while old clients still send the scalar; client built from outdated docs; template authored with {} as a placeholder meaning 'any object'.

Related errors


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