手把手教你写一个JSON在线解析的前端网站1
前言
作为一名Android开发,经常要跟后端同事联调接口,那么总避免不了要格式化接口返回值,将其转换为清晰直观高亮的UI样式以及折叠部分内容,方便我们查看定位关键的信息。
一直以来都是打开Google 搜索json格式化关键字,然后选择Google推荐的前三名的网址,比如

bejson网站:
https://www.bejson.com/
json.cn网站:
https://www.json.cn/
开源中国的JSON解析:
https://tool.oschina.net/codeformat/json
我自己搞的小网站在Google搜索上还排不上号,这里王婆卖瓜,自卖自夸一下,也分享一下子。
json2.top网站:
https://www.json2.top/
之前用的多,基本是直接json.cn来解决问题。现在用自己搭建的json2.top,感觉更爽一些。
技术实现
json2.top这个站点完全是一个前端项目,不涉及一点后端相关的技术。纯jQuery来实现的。实现部分参考了一下json.cn,应该说参考的部分比较多,搬运了不少他们的代码,但是最核心的逻辑还是自己完善思考出来的。
先来看看效果

在左侧输入JSON数据,右侧自动会对左侧的数据进行格式化转换, 变得规整清晰,代码高亮,还能够折叠。特别方便开发者专注于自己的核心数据。
接下来我们来具体讲讲如何实现这个功能,先从代码格式化来开始吧,折叠的部分可以放在后面。
先提前把需要的jQuery.js文件等引入好.
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
然后准备两个div,用于放左侧的输入区域的内容,以及右侧格式化好的内容,具体代码如下
<div class="container">
<div class="split">
<div id="split-0">
<textarea id="json-src" placeholder="Please enter the JSON data... " class="form-control common-font-size"
style="height:100%;padding:10px 10px 10px 30px;border:0;border-radius:0;resize: none;
outline:none;border: 1px solid #eee"></textarea>
</div>
<div id="split-1">
<div id="right-box" class="common-font-size bg-color-ff"
style="width:100%;border:solid 1px #eee;border-radius:0;resize: none;overflow-y:scroll; outline:none;position:relative;flex: 1;flex-grow: 1;">
<p class="editor-tip">Click on key and value to edit</p>
<div id="hidden-message-box" class="alert alert-danger alert-dismissible"
role="alert"
style="display:none;margin-bottom:0;padding:10px 2vw;font-size: calc(var(--target) + 4px);">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<p><i class="fa fa-bell" aria-hidden="true"></i>
tips:
<span id="hidden-message">
Default warning
</span>
</p>
</div>
<div id="line-num"
style="background-color:#fafafa;padding:0px 8px;float:left;border-right:dashed 1px #E5EBEE;display:none;color:#999;position:absolute;text-align:center;over-flow:hidden;">
</div>
<div class="ro" id="json-target"
style="padding:0px 32px;white-space: pre-line;word-wrap:break-word;"></div>
</div>
</div>
</div>
</div>
下面是核心逻辑。
当我们在浏览器上粘贴了没有被格式化过的JSON数据后,我们的思路是先对这个JSON数据先解析,这里先不考虑容错问题,非JSON格式的数据等,只关注最关键的。
默认就用js提供的const obj = JSON.parse(content);来解析json字符串,如果这个json合法,那么我们会得到一个obj的对象,具体这个对象里面的内容都有啥,还需要进一步判断。
没有专门深究过js这门语言,不过总感觉js的类型比较多,又弱语言类型,判断obj具体是什么样的类型就比较无奈。
就以截图中左侧的内容为例来分析吧
{ "sites": [ { "name":"JSON Online Parse" , "url":"www.json2.top" }, { "name":"Google" , "url":"www.google.com" }, { "name":"Introducing JSON" , "url":"www.json.org" } ]}
我们得到的obj是一个map结构,也可以说是是Java里面的对象object,可以理解为obj: {} 在js代码中判断object,用这样的判断typeof obj === "object"
接着在看, sites的结构是个数组,site:[] ,那么在js代码中如何判断数组,用这样的代码Array.isArray(site).
接着以"name":"JSON Online Parse"讲解,解析判断到这一步了,这个是site数组中的第一个对象,然后会对这个对象进行细分判断,取出对应的key是"name", value是"JSON Online Parse",因为在做格式化这一步,我们需要细分的比较细,那么会取出value,来判断value的类型,到了这一步,value已经算是原子类型了,没法在细分了(原谅我用Java语言的说法来描述), 那么如何判断"JSON Online Parse"是什么类型呢,我们明显能看出来,它是个string类型, 就用typeof obj === "string"来判断字符串吧.
由于这个例子没有数字,bool,以及null 那么目前的判断还是不够完善的.
判断数字的代码为typeof obj === "number"
判断bool的代码为typeof obj === "boolean"
字符串为“”以及null的都需要处理分别是obj === "" 以及 obj === null
上面涉及到的几大类型都介绍到了,那么就还是以上文的json数据,来编写代码吧,上文有讲到这个需要一层层的解析,那么可以想象的到,代码是个递归的逻辑,会出现循环调用的情况。
下面是完整的逻辑
function stringifyToHtml(obj, level) {
if (obj === null) {
return "<span class=\"json_null\" contenteditable=\"true\">null</span>";
} else if (obj === "") {
return "<span class=\"json_null\" contenteditable=\"true\">\"\"</span>";
} else if (Array.isArray(obj)) {//说明是数组结构
//console.log(obj);
var str = "<span data-type=\"array\" data-size=\"" + obj.length + "\">" +
"<i style=\"cursor:pointer;\" class=\"fa fa-minus-square-o\" onclick=\"hide(this)\"></i>" + "[<br>";
var blank = generateBlank(level);
if (obj.length > 0) {
for (let i = 0; i < obj.length; i++) {
const item = obj[i];
var json_value = stringifyToHtml(item, level + 1);
if (i == obj.length - 1) {
json_value += "<br>";
} else {
json_value += ",<br>";
}
str = str + blank + json_value;
//console.log(item);
}
}
str += generateBlank(level - 1) + "]</span>";
return str;
} else if (typeof obj === "object") {//是一个object类型
var str = "<span data-type=\"object\">" + "<i style=\"cursor:pointer;\" class=\"fa fa-minus-square-o\" onclick=\"hide(this)\"></i>" + "{<br>";
var blank = generateBlank(level);
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = obj[key];
var json_key = "<span class=\"json_key\" contenteditable=\"true\">\"" + key + "\"</span>" + ": ";
var json_value = stringifyToHtml(value, level + 1);
if (i === keys.length - 1) {
json_value += "";
} else {
json_value += ",<br>";
}
str = str + blank + json_key + json_value;
}
str += "<br>" + generateBlank(level - 1) + "}</span>";
return str;
} else if (typeof obj === "number") {
return "<span class=\"json_number\" contenteditable=\"true\">" + obj + "</span>";
} else if (typeof obj === "boolean") {
return "<span class=\"json_boolean\" contenteditable=\"true\">" + obj + "</span>";
} else if (typeof obj === "string") {
return "<span class=\"json_string\" contenteditable=\"true\">\"" + obj + "\"</span>";
} else {
return "" + obj;
}
}
我们还是以前文的json数据来分析,下面会再贴一遍的
{ "sites": [ { "name":"JSON Online Parse" , "url":"www.json2.top" }, { "name":"Google" , "url":"www.google.com" }, { "name":"Introducing JSON" , "url":"www.json.org" } ]}
在经过JSON.parse(content)处理后,我们得到了一个obj对象,接着需要判断当前obj具体是什么类型,是对象,还是数组,或者是原子类型(number,bool,string,null等类型)。所以在stringifyToHtml()这个函数体的内部,就是根据这些具体的类型来进一步处理的,每一个类型都有对应要展示出来的形式以及存在递归逻辑。在原子类型里面,基本就是展示处理了,只需要做好颜色样式展示,这个可以给定好css样式形式比如className,自己对具体的className编写对应的高亮效果啊就好了。在对象类型以及数组类型中,都还需要进行递归的逻辑。
比如说,刚拿到上面的那串字符串解析好的obj对象,判断它是对象类型后,就需要对齐进行拆分为两部分,key,value,格式化输出是要对key, value都做处理的,key就直接当做字符串展示出来就好,这里用的是var json_key = "<span class=\"json_key\" contenteditable=\"true\">\"" + key + "\"</span>" + ": ";这样的代码展示的,key也有自己的样式效果。然后就是value了,在对value处理的时候,也是要进行递归判断的,因为拿到的这个value,它的结构是个数组,如果不是用这个例子的话,它还可能是个对象,原子类型等等。另外由于对象类型存在多个key,value,所以在判断是对象类型后,还需要for循环这个对象类型呢,具体就参考else if (typeof obj === "object")这个分支判断的内部逻辑了,里面代码写的比较细致。仔细看,就能看懂。
接着说到,在拿到sites是个数组结构后,我们需要开始对sites这个数组结构进行格式化解析展示,处理对应的样式换行等等啊,换行这里不讲。同样先判断Array.isArray(obj)是数组,然后处理最外层的[]中括号符号,这个数组呢,也是需要for循环遍历的,遍历过程中,也存在递归情况。
这两块复杂的讲完了,剩下的都是原子类型啦,只需要取出对应的值,展示对应的样式效果就好了,代码特别简单。参考上文完整的代码吧。
最后
把上述代码整理后,放到了github上的仓库上,地址是https://github.com/xingstarx/jsonParseDemo
github上的项目支持用vercel部署的,这样就可以得到一个属于自己的在线解析工具啦。
直接访问这个https://www.json2.top/也可以,核心代码是一样的,只不过前端样式丰富了一些。
本文内容同步自个人博客站点xingstarx.top 欢迎围观,目前内容还不算多
手把手教你写一个JSON在线解析的前端网站1的更多相关文章
- 只有20行Javascript代码!手把手教你写一个页面模板引擎
http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...
- 手把手教你写一个RPC
1.1 RPC 是什么 定义:RPC(Remote Procedure Call Protocol)--远程过程调用协议 ,RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数 ...
- 让我手把手教你写一个强大、方便使用的 IOC 容器
一.介绍 1.介绍 最近无聊,也没什么事做,没事做总是要给自己找点事情做吧,毕竟人的生活在与折腾.于是,决定自己手动写一个 IOC 的框架.我们知道在 NetCore 的版本里面已经内置了 IOC 容 ...
- 手把手教你写一个java的orm(五)
生成sql:where 上一篇里我们实现了生成insert的sql,下面要开始实现update,delete,select的sql语句了.但是这些语句有一个比较麻烦的地方是:它们一般后面都会有wher ...
- 手把手教你写一个java的orm(一)
写之前的说明 其实吧. 这个东西已经写好了,地址在:https://github.com/hjx601496320/JdbcPlus 这系列文章算是我写的过程的总结吧.(恩系列,说明我可能会写好久,╮ ...
- 手把手教你写一个RN小程序!
时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现 ...
- 手把手教你写一个java的orm(三)
使用反射解析class 上一篇我们完成了class到表映射关系的建立,但是这个并不能被代码正确处理,我们还需要让程序能够正确的识别这些映射关系. 这一篇主要讲的是建立一个从class到表的模型,使我们 ...
- 微信小程序——手把手教你写一个微信小程序
前言 微信小程序年前的跳一跳确实是火了一把,然后呢一直没有时间去实践项目,一直想搞但是工作上不需要所以,嗯嗯嗯嗯嗯emmmmm..... 需求 小程序语音识别,全景图片观看,登录授权,获取个人基本信息 ...
- 手把手教你写一个SpringMVC框架
一.介绍 在日常的 web 开发中,熟悉 java 的同学一定知道,Spring MVC 可以说是目前最流行的框架,之所以如此的流行,原因很简单:编程简洁.上手简单! 我记得刚开始入行的时候,最先接触 ...
- 手把手教你写一个java的orm(完)
生成sql:select 上一篇讲了怎样生成一个sql中where的一部分,之后我们要做事情就简单很多了,就只要像最开始一样的生成各种sql语句就好了,之后只要再加上我们需要的条件,一个完整的sql就 ...
随机推荐
- 近期uniapp使用与总结
弟弟是个uniapp小白,有什么问题欢迎指正. 吃什么饭对于有选择困难的我来说是个大问题,所以想做个根据自己输入的食物随机分配每餐吃的东西,然后就准备用uniapp做这样一个软件,主要是uniapp打 ...
- Dubbo的高级特性:服务治理篇
王有志,一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群:共同富裕的Java人 上一篇中,我们已经在Spring Boot应用中集成了Dubbo,并注册了一个服务提供方和一个服务使用方 ...
- 盘古大模型加持,华为云开天aPaaS加速使能千行百业应用创新
摘要:开天aPaaS,让优秀快速复制,支撑开发者及伙伴上好云.用好云. 本文分享自华为云社区<盘古大模型加持,华为云开天aPaaS加速使能千行百业应用创新>,作者:开天aPaaS小助手. ...
- Python数据分析易错知识点归纳(三):Pandas
三.pandas 不带括号的基本属性 df.index # 结果是一个Index对象, 可以使用等号重新赋值,如: df.index = ['a', 'b', 'c'] df.columns # 结果 ...
- Android 妙用TextView实现左边文字,右边图片
原文: Android 妙用TextView实现左边文字,右边图片 - Stars-One的杂货小窝 有时候,需要文字在左边,右边有个箭头,我个人之前会有两种做法: 使用线性布局来实现 或者使用约束布 ...
- C++之函数的分文件编写
从黑马程序员的c++课里学到的函数的分文件编写 函数的分文件编写 作用:让代码结构更加清晰 函数分文件编写一般有4个步骤 1,创建后缀名为.h的头文件 2,创建后缀名为.cpp的源文件 3,在头文件中 ...
- Redis从入门到放弃(2):数据类型
在Redis中,数据以键值对的形式存储.Redis支持五种主要的数据类型,每种类型都有不同的用途和特性. 本文将介绍Redis的五种数据类型:字符串(string),哈希(hash),列表(list) ...
- rest-apiV2.0.0升级为simplest-api开源框架生态之simplest-jpa发布
什么是 simplest simplest 追求存粹简单和极致. 旨在为项目快速开发提供一系列的基础能力,方便用户根据项目需求快速进行功能拓展 不在去关心一些繁琐.重复工作,而是把重点聚焦到业务. 前 ...
- 如何操作(增、删、改、查)常见的 HTML 元素呢?(包含原生 js 和 JQuery 语法对照)
一.通用的操作示例 1.查询 根据 id 查询(结果为单个对象) // 原生 js 写法 var elementobj = document.getElementById("elementi ...
- Xshell使用技巧及常用配置
Xshell使用 1.调整 Xshell 的终端显示和回滚缓冲区大小 磨刀不误砍柴工,为了更方便地学习 Linux,首先得对终端进行一些调整,步骤如下: 首先通过 xshell 顶部菜单中的文件--& ...