这个问题,已经有非常多人说过,而且由来已久。
大家都提供了不少的解决方法,但是都不够彻底。
一)现在是什么情况
1.使用SpringMvc+ModelAndView+jsp传递值
由于业务需要,通过mv向jsp传递值p,之后jsp解析p,其中p是JSON字符串。
这个串在java中没有问题,但是在jsp中使用JSON.parse的时候遇到了问题,这个问题就是经典的转义字符问题
2.在html/jsp中直接定义字面量json字符串的时候,parse问题,情况同第1种
二)如何解决
1.如果是规避,那么有许多种方法,例如放弃mv传值方式,或者java后台处理好,或者避免使用字面量定义json字符串。不过本文不阐释这个。
2.在使用字面量之前,先转换。
本文通过例子来看看第2种的解决方案
三)解决例子
<html><head> <meta charset="utf-8"> ` <title>this a simple 特别字符测试</title> <style> #dDivMain { text-align: center; margin-left: 20%; margin-right: 20%; margin-top: 45px; } span { word-wrap: break-word; word-break: break-all; text-align: left; display: block; } table { width: 100%; display: inline-table; border-spacing: 0rem; } th { background-color: blue; color: yellow; } th, td { border-style: solid; border-width: 1px; border-color: green; } textarea { word-break: break-all; word-wrap: break-word; overflow-y: scroll; width: 50%; } </style> </head>
<body> <div id="dDivMain"> <span>js中存在一些异常的字符,这些字符必须使用转义的方式才可以表达 </span> <hr> <span>以下是常见的转义字符:</span> <table> <thead> <th>字符</th> <th>含义</th> </thead> <tbody> <tr> <td>\'</td> <td>单引号</td> </tr> <tr> <td>\"</td> <td>双引号</td> </tr> <tr> <td>\&</td> <td>和号</td> </tr> <tr> <td>\\</td> <td>反斜杠</td> </tr> <tr> <td>\n</td> <td>换行</td> </tr> <tr> <td>\r</td> <td>回车符</td> </tr> <tr> <td>\t</td> <td>制表符</td> </tr> <tr> <td>\b</td> <td>退格</td> </tr> <tr> <td>\f</td> <td>换页</td> </tr> </tbody> </table> <span>1)这些转义字符如果是普通应用,那么脚本不会报告错误</span> <span>2)但是如果直接书写,用作一些JSON处理,就会异常</span> <hr> <div> <input type="button" value="显示JSON属性-From Server" onclick="getJsonValue()"> <input type="button" value="显示JSON属性-Local String" onclick="getJsonValueFromLocal()"> <input type="button" value="显示JSON属性-From Object" onclick="getJsonValueFromObject()"> </div> <div id="dDivContent" style="display: flex;margin-top: 10px;"> <textarea rows="10" cols="50" id="dTjsonstr"></textarea> <textarea rows="10" cols="50" id="dTjsonValue"></textarea> </div> </div>
</body> <!-- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> --> <script src="jquery-3.6.0.js"></script> <script> function getJsonValue() { $.get("http://localhost:9999/map/getJson", function(response) { let str = JSON.stringify(response); let now = new Date(); $("#dTjsonstr").val(now + "\najax解析\n" + str); }); }
function getJsonValueFromLocal() { let jstr = '{"address":"中国\"","sex":"\r男\r\n"}'; //let jstr = '{"address":"中国","phone":"123888&","sex":"男\\r\\n","name":"luzhifei\\t"}'; jstr = replaceEscapeChar(jstr); let jo = JSON.parse(jstr, function(k, v) { console.log(k + ":" + v); return v; }); let txt = jo.address; $("#dTjsonValue").val(txt); }
function getJsonValueFromObject() { let jo = { name: "luzhifei\t", sex: "男\n", address: "中国", phone: "13333&&" } let txt = jo.name + jo.sex + jo.address; $("#dTjsonValue").val(txt); }
/** * @description 最彻底的方法是分解之后替换再合并 */ function replaceEscapeChar(sSource) { const escapeCharArr = [{ key: '\"\"', value: '\\"\"' }, { key: '\t', value: '\\t' }, { key: '\n', value: '\\n' }, { key: '\r', value: '\\r' }, { key: '\t', value: '\\t' }]; let tmpStr = sSource; for (let i = 0, len = escapeCharArr.length; i < len; i++) { let arr = tmpStr.split(escapeCharArr[i].key); tmpStr = arr.join(escapeCharArr[i].value); } return tmpStr; } </script>
</html>
运行结果如下图:
这个例子说明了3个问题:
a)使用ajax接受的JSON对象,不存在解析问题
b)如果使用简单的对象定义方式,那么不存在异常字符问题
c)使用mv传递(本例没有示范)和字面量定义json字符串的时候,可以使用替换的方式解决parse问题
例子中有意义的代码如下:
function replaceEscapeChar(sSource) { const escapeCharArr = [{ key: '\"\"', value: '\\"\"' }, { key: '\t', value: '\\t' }, { key: '\n', value: '\\n' }, { key: '\r', value: '\\r' }, { key: '\t', value: '\\t' }]; let tmpStr = sSource; for (let i = 0, len = escapeCharArr.length; i < len; i++) { let arr = tmpStr.split(escapeCharArr[i].key); tmpStr = arr.join(escapeCharArr[i].value); } return tmpStr; }
不过我们希望,以后的浏览器升级之后,程序员不用那么辛苦了。
至少不要幸苦大家,而只是小小麻烦下浏览器厂商!