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' 共同作用的结果。

相关推荐
摘星编程7 小时前
OpenHarmony + RN:Placeholder文本占位
javascript·react native·react.js
计算机毕设VX:Fegn08958 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
没差c9 小时前
springboot集成flyway
java·spring boot·后端
三水不滴9 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
笨蛋不要掉眼泪9 小时前
Spring Boot集成LangChain4j:与大模型对话的极速入门
java·人工智能·后端·spring·langchain
摘星编程10 小时前
React Native + OpenHarmony:Spinner旋转加载器
javascript·react native·react.js
普通网友11 小时前
新手必看!HCCDA-HarmonyOS & Cloud Apps 实验保姆级教程
javascript·angular.js
用户新11 小时前
V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
前端·javascript
Next_Tech_AI11 小时前
别用 JS 惯坏了鸿蒙
开发语言·前端·javascript·个人开发·ai编程·harmonyos
-凌凌漆-12 小时前
【vue】选项式api与组合式api
前端·javascript·vue.js