JS的JSON.parse问题

这个问题,已经有非常多人说过,而且由来已久。

大家都提供了不少的解决方法,但是都不够彻底。

 

一)现在是什么情况

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-aligncenter;
            margin-left20%;
            margin-right20%;
            margin-top45px;
        }
        
        span {
            word-wrapbreak-word;
            word-breakbreak-all;
            text-alignleft;
            displayblock;
        }
        
        table {
            width100%;
            displayinline-table;
            border-spacing0rem;
        }
        
        th {
            background-colorblue;
            coloryellow;
        }
        
        th,
        td {
            border-stylesolid;
            border-width1px;
            border-colorgreen;
        }
        
        textarea {
            word-breakbreak-all;
            word-wrapbreak-word;
            overflow-yscroll;
            width50%;
        }
    </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;
    }

 

不过我们希望,以后的浏览器升级之后,程序员不用那么辛苦了。

至少不要幸苦大家,而只是小小麻烦下浏览器厂商!

 

posted @ 2021-08-29 02:00  正在战斗中  阅读(67)  评论(0编辑  收藏  举报