dromara/Sa-Token · error · RuntimeException

值无法转化为SoMap: ${value}

Error message

值无法转化为SoMap: ${value}

What it means

Thrown by SoMap.getMap(key) when the value stored under key is neither null, nor a java.util.Map, nor a JSON String — the only three shapes the method can convert into a SoMap. It is a plain RuntimeException from the demo OAuth2 client's utility map, indicating the caller assumed a nested object where the data actually holds a scalar or a List.

Source

Thrown at sa-token-demo/sa-token-demo-oauth2/sa-token-demo-oauth2-client/src/main/java/com/pj/utils/SoMap.java:158

	/** 转为Date并返回,根据格式: yyyy-MM-dd HH:mm:ss */
	public Date getDateTime(String key) {
		return getDateByFormat(key, "yyyy-MM-dd HH:mm:ss");
	}

	/** 转为Map并返回 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SoMap getMap(String key) {
		Object value = get(key);
		if(value == null) {
			return SoMap.getSoMap();
		}
		if(value instanceof Map) {
			return SoMap.getSoMap((Map)value);
		}
		if(value instanceof String) {
			return SoMap.getSoMap().setJsonString((String)value);
		}
		throw new RuntimeException("值无法转化为SoMap: " + value);
	}

	/** 获取集合(必须原先就是个集合,否则会创建个新集合并返回) */
	@SuppressWarnings("unchecked")
	public List<Object> getList(String key) {
		Object value = get(key);
		List<Object> list = null;
		if(value == null || value.equals("")) {
			list = new ArrayList<Object>();
		}
		else if(value instanceof List) {
			list = (List<Object>)value;
		} else {
			list = new ArrayList<Object>();
			list.add(value);
		}
		return list;
	}

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Inspect the actual value class before calling getMap: use soMap.get(key) and check instanceof Map / is JSON String.
  2. Verify the upstream OAuth2 server response actually nests an object at that key (log the raw JSON once).
  3. If the value arrives as a JSON string, ensure it is a JSON object literal, not an array or scalar.
  4. Prefer the typed getModel(key, Class) accessor or check isNull(key)/getString(key) first when the schema is uncertain.

Example fix

// before
SoMap token = soMap.getMap("data");

// after
Object data = soMap.get("data");
if (data == null || !(data instanceof Map || data instanceof String)) {
    throw new IllegalStateException("unexpected response: " + soMap.getString("msg"));
}
SoMap token = soMap.getMap("data");
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = soMap.get(key);
if (v == null || v instanceof Map || v instanceof String) {
    SoMap m = soMap.getMap(key); // safe
} else {
    // do not call getMap
}

Type guard

boolean isMapLike(Object v) { return v == null || v instanceof Map || v instanceof String; }

Prevention

When it happens

Trigger: Calling soMap.getMap("token") (or similar) when the parsed JSON/parameters contain a non-object under that key, e.g. an Integer, Boolean, or List. Typical in the OAuth2 client when processing an access-token response whose schema changed or whose error body put a scalar where an object was expected.

Common situations: The OAuth2 server returned an error JSON (e.g. {"code":500,"msg":"..."}) where the client unconditionally does getMap("data"); or the response structure differs between sa-token versions.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/6615c9ee9fed276a. Report an issue: GitHub.