JSON格式化

发布时间:2025-12-09 11:52:06 浏览次数:2

我个人主要是做一些后端的工作,比如php、python、c之类的,c比较少,最主要的是php,不过我非常喜欢js,所以经常会愿意去写一些小玩意自娱自乐。

今天在测试接口的时候,使用原生js的XMLHttpRequest去请求,直接使用document….innerHTML输出到页面,因为没有浏览器的json格式化没有生效,所以接口响应的json数据就看起来很不舒服。

于是乎,我就想起了为啥我自己不能实现一个,应该不是很难吧。

我仔细思考了一下,这玩意不就是遇到大括号、中括号和中括号就换行吗,每行还有个缩进,人家再高级一点的还有颜色,折叠功能、缩进对齐线之类的,于是我觉得一步一步来,先把格式化和颜色实现出来,后面的折叠、动画和缩进对齐线再慢慢做。

电影有句话说的好啊:“步子迈大了,咔,容易扯着蛋”。

扯了这老些没用的,下面开始我的正经思路:

合法的JSON字符串是一个单行字符串,边界符号是“{} []”,键值对之间是以英文逗号“,”作为分隔,键和值之间是用英文冒号“:”进行分隔。JSON内的字符串必须以双引号包括在外侧,数字类型或布尔类型可以不使用双引号包括。逗号分隔符的后面必须至少存在一个键值对(即末尾的键值对的后面不能有逗号分隔符了,这里的逗号指的是键值对分隔符,而不是指值内的逗号字符串)。

看看别人优秀的是什么样子的。

从某平台的json格式化服务截取

可以发现在“{, [”的后面都会有一个换行,每个键值对的后面都有一个换行,在符号“], 和 }, ”的后面都会有一个换行。

而且格式化后的JSON是有“结构区块”的,从缩进来区分不同的结构块,这一点有点像python,不过这有点牵强,格式化这样做的目的是为了能够很清晰的查看JSON的结构,与python的目的是有本质的区别的。

从截图来看,只要遇到一个“{ 或 [”,就要出现缩进,而且可以看出,缩进是随着遇到的个数增加的,这是成正比啊。而且只要遇到“]或}”,缩进就要少一个。

说到这里是不是就有感觉了,缩进就是在匹配括号啊,这匹配括号在逆波兰式里的操作啊,不就是基础的数据结构“栈”吗。

那我对整个字符串进行遍历判断是不就能做到了,那有了思路就可以动手了,能动手我就不在这里扯?了。

<!-- 这里在页面放一个pre标签,让输入的结构按照我们需要的形式展现 --><pre ></pre>

假设我有一个jsonStr,我想要格式化它。

var jsonStr = '{"state":{"code":0,"success":true,"ok":1},"body":[{"count":2394,"dbName":"star_all"},{"count":133,"dbName":"star"},{"count":7,"dbName":"zy"},{"count":1,"dbName":"gordon_test"}]}';
function format(str){    var stack = []; //栈-用于括号匹配    var tmpStr = '';    //新格式化JSON字符串    var len = str.length;   //原始JSON长度    //遍历每一个字符    for (let i = 0; i < len; i++) {        //当遇到结构块起始结构        if (str[i] == '{' || str[i] === '[') {            //起始结构后面直接换行              tmpStr += str[i] + "n";            //入栈            stack.push(str[i]);                        //这里的意思是结构块起始的下一行开始就会有一个缩进,缩进量与遇到的结构块起始符个数成正比1:1            tmpStr += "t".repeat(stack.length);        }         //当遇到结构块结束符        else if (str[i] == ']' || str[i] === '}') {            //因为本身JSON格式是固定的,所以括号一定是成对的,这里先不考虑错误的json数据            //遇到结束符就退栈,            stack.pop();            //结束符本身输出到下一行,并减少一个缩进            tmpStr += "n"+"t".repeat(stack.length) + str[i];        }         //当遇到逗号的时候        else if (str[i] == ',') {            //逗号后方直接换行,以及下一行的缩进处理            tmpStr += str[i] + "n" + "t".repeat(stack.length);        }         else {            //其他字符直接复制            tmpStr += str[i];        }    }    return tmpStr;}

返回的数据放到<pre>标签内

document.querySelector('#json').innerHTML = format(jsonStr);

输出的效果如下图

制表符t稍微有点远,当然使用4个 也可以,别纠结~

这黑白色的不美观,那就给上个色呗,看看人家的,括号一个颜色,键值对一个颜色,值一个颜色,我不能抄它的,我觉得字符串,数字、布尔都分别用一种颜色就行,这个实现就都能实现了。

那既然需要分开使用不同的颜色,那么必然就涉及CSS了,每个结构就得有HTML结构了,我直接用正则是不是就解决了。

先写个CSS样式把

.bold{    font-weight: 900;}.string-color {    color: darkred;}.token {    color: darkgreen;}.number {    color: green;}.bool {    color: orange;}
//使用捕获,匹配全部的边界符号,class使用tokentmpStr = tmpStr.replace(/([{[]}])/g, '<span >$1</span>');//使用零宽断言和捕获,匹配全部的两侧是双引号的字符串,class使用stringtmpStr = tmpStr.replace(/(?<=")(w+)(?=")/g, '<span >$1</span>');//使用零宽断言,匹配全部的前面位置是冒号,后面是逗号或换行的数字类型值tmpStr = tmpStr.replace(/(?<=:)(d+)(?=[,n])/g, '<span >$1</span>');//同理匹配布尔,tmpStr = tmpStr.replace(/(?<=:)(true|false)(?=[,n])/g, '<span >$1</span>');

零宽断言就是匹配一个位置,分负向零宽断言和正向零宽断言,不知道的可以搜索一下。

效果还行

到这里就初步完成了一个还算能入眼的基础JSON格式化小方法。后续再加个闪电爆炸的特效,下次再分享~

json 格式化
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477