一、前置核心知识点
✅ 核心概念梳理:后台 Map/List → JSON 格式 对应关系
本文核心实现的是 后端 Java 返回「Map 集合 (内部包含单个 / 多个 List 集合)」→ 转 JSON 字符串响应给前端 → JS/Ajax 解析 JSON 并遍历数据 的完整流程,也是 JavaWeb + 前端开发中高频的交互场景,核心对应关系必须牢记:
- 后端单个 List 集合 → 使用 net.sf.json.JSONArray.fromObject(list) 转成 JSON 数组格式字符串,前端接收后可直接遍历,无需额外转换;
- 后端Map 集合 (内部包含多个 List / 对象) → 使用 net.sf.json.JSONObject.fromObject(map) 转成 JSON 对象格式字符串,该 JSON 对象的key是 Map 的键,value是对应的 List 集合 / 数据,前端接收后需要先转成 JS 对象,再通过对象.key获取内部集合遍历;
- 前端解析的核心:Ajax 返回的响应数据本质是纯文本字符串,必须转换成 JavaScript 的「对象 / 数组」才能遍历取值,这也是本文所有解析写法的核心前提。
✅ 后端核心 JSON 转换工具说明
本文中后端使用的 net.sf.json.JSONObject、net.sf.json.JSONArray 是java-web 开发中主流的 JSON 转换工具,依赖之前讲解的json-lib-2.2.2-jdk15.jar及相关依赖包,作用是将 Java 的Map、List、实体类等数据结构,无缝转为符合标准语法的 JSON 格式字符串,保证前端可以正常解析,是前后端数据交互的核心桥梁。
二、JS 遍历 Ajax 返回的 JSON 数据(基础 Map / 数组型)

✅ 核心知识点
- 遍历方式说明:该写法是 JS 原生的for-in遍历,适用于前端接收的是 JSON 数组 / 类数组对象(对应后端单个 List 转的 JSONArray);
- hasOwnProperty(i) 核心作用:过滤掉对象的原型链属性,只遍历自身的属性 / 数组的下标,避免遍历到 JS 原生对象的内置方法 / 属性,导致取值报错或遍历异常,这是for-in遍历的必加优化项,规范写法;
- 取值规则:datares[i] 表示获取数组的第i个元素(Java 实体类转的 JSON 对象),通过.直接调用对象的属性(deptid、deptname),属性名与后端 Java 实体类的属性名完全一致;
- 业务场景:该写法多用于下拉框<option>动态赋值,是前端接收后端部门列表、角色列表等单集合数据的经典应用。
三、Ajax 请求返回 Map,并遍历

✅ 核心知识点(重中之重)
- 后端数据结构:本次 Ajax 请求的后端返回值是 Java 的 Map 集合,该 Map 中包含了一个key="groupList"的键,对应的值是List<Group>集合,后端通过JSONObject.fromObject(returnMap)将整个 Map 转为 JSON 对象字符串;
- 前端解析核心代码 var obj=eval("(" + msg + ")") 详解: Ajax 的success回调中,msg是后端返回的纯 JSON 格式字符串,无法直接遍历和调用属性; eval("("+msg+")") 的作用:将 JSON 字符串强制解析为 JavaScript 原生对象,加小括号()的原因是:JSON 字符串的首尾是{},JS 引擎会默认识别为「代码块」,包裹括号后强制转为「对象表达式」,才能完成正确解析; 该写法是老旧项目中最常用的解析方式,兼容所有浏览器,无任何依赖。
- $.each(obj.groupList, function(i,item){}) 遍历规则: obj.groupList:解析后的 JS 对象中,通过.调用groupList属性,获取到后端传入的 List 集合对应的JSON 数组; jQuery 的$.each():第一个参数i是数组的下标,第二个参数item是数组当前项的对象,直接通过item.groupName调用对象属性,与后端实体类的groupName属性一一对应; 优势:$.each()是 jQuery 封装的遍历方法,比原生for-in更简洁,且对数组 / 对象的兼容性更高。
四、后台数据转换 + 前台解析适配规则
发送请求到后台,然后后台通过各种操作,得到相应数据 如果数据为 map,map 中包含了多个 list,

后台这样转换,然后前台转换下:var obj=eval("(" + msg + ")"); 就可以遍历里面的数据了(注意:net.sf.json.JSONArray.fromObject(returnMap.get("list")).toString())这样是转换单个集合时适用,然后前台直接遍历即可,不需要强转
JSONArray 转包含多个 list 的 map 时适用。
✅ 核心知识点
✔️ 规则一:后端返回「单个 List 集合」→ 用 JSONArray 转换
- 后端转换代码:JSONArray.fromObject(returnMap.get("list")).toString()
- 转换结果:标准的JSON 数组字符串,格式如 [{"name":"测试1"},{"name":"测试2"}]
- 前端解析:无需执行 eval () 转换,可直接遍历!因为返回的是纯数组格式,Ajax 回调的msg可直接作为数组使用,$.each(msg, ...) 直接遍历即可,极简高效;
- 适用场景:只需要向前端返回一个列表数据(如部门列表、角色列表)。
✔️ 规则二:后端返回「Map 集合 (含多个 List / 数据)」→ 用 JSONObject 转换
- 后端转换代码:JSONObject.fromObject(returnMap.get("map")).toString()
- 转换结果:标准的JSON 对象字符串,格式如 {"groupList":[{"name":"测试1"}], "roleList":[{"code":"001"}]}
- 前端解析:必须执行 eval ("("+msg+")") 转换!将 JSON 字符串转为 JS 对象后,才能通过对象.key获取内部的各个 List 集合,再进行遍历;
- 适用场景:需要向前端一次性返回多个列表数据(如同时返回角色列表、用户组列表),是开发中多数据聚合返回的主流方式。
✔️ 核心区别总结
- JSONArray.fromObject() → 转JSON 数组 → 前台无转换,直接遍历;
- JSONObject.fromObject() → 转JSON 对象 → 前台必须转 JS 对象,再取值遍历。
五、后端开发核心注意事项
✅ 注意 1:后台 pw.print 和 pw.println 的使用差异
还有后台 pw.print 和 pw.println 的使用也要注意,当单个数据 0,1 来给后台判断时,pw.println 会带换行符,永远不等于 0,1.
✔️ 避坑说明
- PrintWriter.print(String str):只输出纯字符串内容,无任何多余字符,返回给前端的内容就是后端拼接的完整数据,无冗余;
- PrintWriter.println(String str):输出字符串后,会自动追加一个换行符 (\n) 和回车符 (\r);
- 致命问题:如果后端返回的是单个标识值(如0/1/success/fail),用println返回后,前端接收到的实际是"0\n"/"1\r\n",此时前端判断msg == 0 或 msg == 1 永远为false,因为字符串包含了换行符,与纯数字 / 纯字符不匹配;
- ✅ 开发规范:前后端 Ajax 交互返回数据时,统一使用 pw.print (),禁止使用 pw.println (),避免因隐藏的换行符导致前端判断逻辑失效。
✅ 注意 2:返回中文乱码处理的代码顺序问题

这两句对返回乱码处理也要特别注意先后顺序。PrintWriter pw =response.getWriter (); 在前的话,转换也不起作用!
✔️ 避坑说明
- 代码执行逻辑:response.getWriter() 表示获取响应的输出流对象,一旦创建了该对象,就意味着后端的响应头、响应编码的配置已经定型生效,后续再修改响应配置将完全无效;
- 乱码根源:如果先执行PrintWriter pw = response.getWriter();,再执行response.setContentType("text/plain;charset=UTF-8");,编码配置不会被生效,后端返回的中文 JSON 数据会以默认编码(ISO-8859-1)输出,前端接收到后就是乱码;
- ✅ 强制规范:所有响应头 / 编码配置,必须写在获取 PrintWriter 输出流之前,这是解决 JavaWeb 后端返回中文乱码的核心规则,无例外!
- 拓展配置:如果返回的是纯 JSON 数据,推荐将响应类型配置为response.setContentType("application/json;charset=UTF-8");,语义更精准,前端解析更友好,同样要保证该代码在getWriter()之前。