后端明明返回的数据格式是Map的,为啥我接到以后格式变成了Object?
事情的起因是这个接口返回的是一个Map然后前端接受以后打印出来的是一个ojbect
前端小伙伴(比如用 JavaScript)兴冲冲地调用这个接口:
javascript
fetch('/getEquipment')
.then(response => response.json())
.then(data => {
console.log("deviceRunState类型:" + typeof res.data.deviceRunState);
console.log(res.data.deviceRunState);
});
运行结果往往令人困惑:

明明 Java 代码里清清楚楚写着返回 Map<String, Object>
,怎么一到前端就成了一个普普通通的 object
?这个看似简单的现象背后,其实藏着两个关键的技术真相。
原因1:JSON的原因
当你的 Java Map 离开后端,准备前往前端时,它必须进行一次长途运输。这个运输工具就是 JSON 。JSON 是前后端数据交换的通用语言,但它有个特点:只关心数据的结构和值,完全不在乎数据在原始语言中的具体类型名称。
- 后端打包(序列化): Spring Boot(或其他框架)使用如 Jackson 的库,把 Java
Map
对象仔细拆解。它记录下所有的键值对(key-value) JSON 字符串里,没有任何地方标注这是一个 HashMap" 。它只描述了这里有一个对象,里面有键以及对应的值。值是一个数组(用[]
表示)。原始类型(字符串、数字、布尔值、null)和它们的值会被保留,但容器类型(Map, List, Set 等)的具体类型信息在转换过程中被彻底丢弃了。JSON 标准本身根本不支持记录这种元信息。
原因2:JavaScript 可能不认识Map
当前端 JavaScript 收到这个 JSON 字符串,它需要把它变回自己能操作的数据。它使用 JSON.parse()
方法:
javascript
runstate_map = new Map(Object.entries(res.data.deviceRunState));
console.log(typeof runstate_map); // 输出: "object"
//然后获取runstate_map的值的时候,就可以直接使用map.get("")就行了
if(runstate_map!=null){
var runstate = runstate_map.get(item.identifier);
console.log("runstate:" + runstate);

- 遇到
{}
: 它就创建一个新的 JavaScript 普通对象 。这种对象的核心功能就是存储键值对,和 Java 的Map
在基础功能上非常相似(增删改查键值对)。 - 遇到
[]
: 它就创建一个 JavaScript 数组 (Array)。 - 遇到字符串、数字等: 就创建对应的 JavaScript 基本类型。
核心问题在于:JavaScript 中没有一个叫做 Map
的基础数据类型来表示这种键值对集合! 在 JavaScript 的世界观里:
typeof
操作符: 对于任何非基本类型(非 string, number, boolean, symbol, undefined, null)的值,typeof 返回的结果都是"object"。- ES6 的
Map
: 现代 JavaScript (ES6) 确实引入了Map
类型,它比普通对象更适合某些键值对场景(比如键可以是任意类型、保持插入顺序等)。但是,JSON.parse()
默认行为绝对不会把 JSON 对象{}
解析成 JavaScript 的Map
实例! 它只会解析成普通的 JavaScript 对象。
所以,当你在前端执行 typeof data 时,data 就是 创建出来的一个标准 JavaScript 普通对象,typeof 报告它是 "object"
是完全准确且符合语言规范的。它确实就是一个 Object,而不是一个 Java 后端返回的Map格式。
总结
Java 后端的 Map 经过 JSON 序列化"运输"后,丢失了"Map"这个类型标签,变成了只描述结构的纯数据。前端 JavaScript 根据 JSON的语法,自然创建出它最基础的对象类型------普通对象。JavaScript 的 typeof 运算符诚实地将其报告为 "object"
。这不是 bug,而是 JSON 作为通用数据格式的固有特性(不保留语言特定类型)与 JavaScript 类型系统(typeof
对非原始类型返回 'object'
) 共同作用的结果。