Map穿越JSON边境后惨遭“洗白”?前端:我只认识Object!

后端明明返回的数据格式是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 的世界观里:

  1. typeof 操作符: 对于任何非基本类型(非 string, number, boolean, symbol, undefined, null)的值,typeof 返回的结果都是"object"。
  2. 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' 共同作用的结果。

相关推荐
问今域中8 分钟前
Spring Boot 请求参数绑定注解
java·spring boot·后端
码界奇点13 分钟前
基于Vue3与TypeScript的后台管理系统设计与实现
前端·javascript·typescript·vue·毕业设计·源代码管理
计算机程序设计小李同学15 分钟前
婚纱摄影集成管理系统小程序
java·vue.js·spring boot·后端·微信小程序·小程序
ashcn200118 分钟前
水滴按钮解析
前端·javascript·css
爱吃奶酪的松鼠丶26 分钟前
React长列表,性能优化。关于循环遍历的时候,key是用对象数据中的ID还是用索引
javascript·react.js·性能优化
xkxnq1 小时前
第二阶段:Vue 组件化开发(第 17天)
javascript·vue.js·ecmascript
豆苗学前端1 小时前
你所不知道的前端知识,html篇(更新中)
前端·javascript·面试
一 乐1 小时前
绿色农产品销售|基于springboot + vue绿色农产品销售系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端·宠物
sophie旭1 小时前
内存泄露排查之我的微感受
前端·javascript·性能优化
3***68841 小时前
Spring Boot中使用Server-Sent Events (SSE) 实现实时数据推送教程
java·spring boot·后端