flipped-aurora/gin-vue-admin · error

apis 需为JSON数组或逗号分隔字符串

Error message

apis 需为JSON数组或逗号分隔字符串

What it means

parseAPIItems in role_api_batch_assigner.go accepts the `apis` input as either a JSON array of {path,method} objects or a comma-separated string of path:method items. It throws this error when the input is neither — i.e. the parsed value is not a []interface{} array and not a string, so it falls into the default branch. It is a strict input-format validation guard before path+method items are normalized and deduplicated.

Source

Thrown at server/mcp/role_api_batch_assigner.go:182

		// 形如 [{"path":..,"method":..}] 若按逗号切分会碎成垃圾策略,先尝试按 JSON 数组解析
		if strings.HasPrefix(trimmed, "[") {
			var arr []any
			if err := json.Unmarshal([]byte(trimmed), &arr); err == nil {
				return parseAPIItems(arr)
			}
		}
		for part := range strings.SplitSeq(trimmed, ",") {
			if strings.TrimSpace(part) == "" {
				continue
			}
			path, method, err := parseAPIItemString(part)
			if err != nil {
				return nil, err
			}
			appendItem(path, method)
		}
	default:
		return nil, errors.New("apis 需为JSON数组或逗号分隔字符串")
	}

	// 批内去重(按归一化后的 path+method)
	seen := make(map[string]struct{}, len(items))
	deduped := items[:0]
	for _, item := range items {
		path, method := normalizePolicy(item.Path, item.Method)
		key := method + " " + path
		if _, ok := seen[key]; ok {
			continue
		}
		seen[key] = struct{}{}
		deduped = append(deduped, item)
	}
	return deduped, nil
}

// parseAPIItemString 解析"METHOD /path"或"/path"形式的单条API,方法缺省为POST

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Send apis as a JSON array of {path, method} objects: apis=[{"path":"/user/list","method":"GET"}]
  2. Or send a comma-separated string of path:method items: apis=/user/list:GET,/user/create:POST
  3. Check the request content-type / field encoding — ensure the value is not being double-wrapped or coerced into an object by the client serializer
  4. Add client-side validation that rejects non-array, non-string apis values before submission

Example fix

// before
{ "apis": { "path": "/user/list", "method": "GET" } }
// after
{ "apis": [ { "path": "/user/list", "method": "GET" } ] }
// or
{ "apis": "/user/list:GET" }
Defensive patterns

Strategy: validation

Validate before calling

const apis = payload.apis
const isJsonArray = Array.isArray(apis) || (typeof apis === 'string' && apis.trim().startsWith('['))
const isCsv = typeof apis === 'string' && /:?[A-Za-z]+\s*,/.test(apis)
if (!isJsonArray && !isCsv) throw new Error('apis must be a JSON array or comma-separated path:method string')

Type guard

function isValidApis(v) {
  if (Array.isArray(v)) return v.every(i => i && typeof i.path === 'string' && typeof i.method === 'string')
  return typeof v === 'string'
}

Try / catch

try {
  await assignRoleApis({ apis })
} catch (e) {
  if (String(e.message).includes('JSON数组或逗号分隔')) {
    console.error('apis format invalid, use [{path,method}] or "path:METHOD,..."', e)
  } else { throw e }
}

Prevention

When it happens

Trigger: Calling the batch-assign Handle flow with apis as a bare object (e.g. {"path":"/x","method":"GET"} without array wrapping), a number, boolean, or null. Also when the client sends form data or a nested structure instead of a JSON array string like '[{"path":"/a","method":"GET"}]' or 'path1:GET,path2:POST'.

Common situations: Frontend code passing the wrong shape after refactoring (single object instead of array); API consumers omitting the field wrapper when only one API is assigned; hand-rolled curl calls guessing the format; template/generated code sending an object keyed by path.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/edcdfa4d784c0b4f. Report an issue: GitHub.