可视化编辑json数据——json editor

最近开发了一个chrome插件,需要找一个轻量级的可视化编辑json的组件。当然使用ace这一类组件是完全可以的,但是个人感觉比较重量。于是查阅了一些资料,整理如下。

对于一个json字符串,通过javascript的如下方法可以很方便的对其格式化:

var jsonObj = JSON.parse(json_val)   //把json字符串转为json对象
var formattedStr = JSON.stringify(jsonObj, null, 4);

将formattedStr字符串可以输出到textarea组件中。这种方法简单粗暴,缺少了json的折叠、高亮等功能;更进一步,可以通过以下两个组件实现可视化展示json数据:

更多见:https://blog.csdn.net/liuxiao723846/article/details/103774795

以上,是如何可视化展示json数据的方法,而这次的需求不光是要可视化展示,还要可以编辑json数据,于是在github上找到了这个代码(https://github.com/dblate/jquery.json-editor),在demo页面(https://dblate.github.io/jquery.json-editor/)中试用了一下,感觉已经满足了我的需求(可编辑+小巧)。

阅读源码发现该项目的代码非常简单,简单到几乎没有任何实现,完全依赖底层的jquery.json-viewer.js库(上面已介绍)。所以,接下来我们就直接使用jquery.json-viewer.js这个库来实现可以编辑的json格式化组件。

先上例子:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/json-viewer/jquery.json-viewer.css" rel="stylesheet">
</head>
<style type="text/css">
    #json-display {
        border: 1px solid #000;
        margin: 0;
        padding: 8px 15px;
        min-height: 300px;
        background: #1c2833;
        color: #fff;
    }
</style>
<body>
<div style="padding: 40px 20px 0px 20px;">
    <div>
        <pre id="json-display" contenteditable="true"></pre>
    </div>
    <br>
    <input type="button" id="format_btn" value="格式化" onclick="format_btn();" />
</div>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/json-viewer/jquery.json-viewer.js"></script>
<script>
    $(document).ready(function(){   
        var jsonObj = {"a":1,"b":"test"};
        $("#json-display").jsonViewer(jsonObj,{withQuotes: true});//格式化展示
    });
    function format_btn() {
        var jsonval = $("#json-display").text();
        var jsonObj = JSON.parse(jsonval);   //把json字符串转为json对象
        $("#json-display").jsonViewer(jsonObj,{withQuotes: true});//格式化展示
    }
</script>
</body>
</html>

效果如下图:

1、如何做到的可编辑?

contenteditable 属性是 HTML5 中的新属性;该属性规定元素内容是否可编辑。那么通过该数据,就可以对jquery.json-viewer.js中的<pre>节点进行编辑了。例如:

<!DOCTYPE HTML>
<html>
<body>

<div contenteditable="true">这是一段可编辑的段落。请试着编辑该文本。</div>

</body>
</html>

2、复制时去掉格式:

通过contenteditable属性,将<pre>变成可编辑的,当把网页中的json数据复制到编辑框中,发现会把格式也复制进去,例如:

解决方案:

$(document).ready(function(){
    //paste clean format
    $("#json-display").on("paste", function (e) {
        textInit(e)
    });
});

function textInit(e) {
    e.preventDefault();
    var text;
    var clp = (e.originalEvent || e).clipboardData;
    if (clp === undefined || clp === null) {
        text = window.clipboardData.getData("text") || "";
        if (text !== "") {
            if (window.getSelection) {
                var newNode = document.createElement("span");
                newNode.innerHTML = text;
                window.getSelection().getRangeAt(0).insertNode(newNode);
            } else {
                document.selection.createRange().pasteHTML(text);
            }
        }
    } else {
        text = clp.getData('text/plain') || "";
        if (text !== "") {
            document.execCommand('insertText', false, text);
        }
    }
}

 3、遇到问题一:

输入如下的json数据进行格式化,格式化后c节点的value值没有被引号包裹:

{"a":1,"b":"test","c":"http://test.com"}

 结果如下:(这样会破坏了原始json数据)

说明:对于json数据结构的标准,key是必须要有双引号;value则根据类型,如果是字符串需要使用双引号。json-viewer.js库可以通过如下属性,设置key是否使用引号:

$("#json-display").jsonViewer(jsonObj,{withQuotes: true});

解决方法:

从json-viewer.js源码可以发现,源码中会判断value是否是url,如果是则直接输出

 所以,可以直接修改源码,添加上双引号。

 4、遇到问题二:

输入如下json数据进行格式化,格式化后extra节点的value值也被当作了json,再次被格式化:

{"a":1,"extra":"{\n  \"circles\" : [\n    \"史莱姆\"\n  ],\n  \"tags\" : [\n    \"危险的她\"\n  ],\n  \"topics\" : [\n    \"好久不见\"\n  ]\n}"}

结果如下:(破坏了原始json 数据)

解决方法: 

使用JSON.stringify方法保留字符串中的\n等,然后直接输出:

if (typeof json === 'string') {
      // Escape tags and quotes
      json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

      if (options.withLinks && isUrl(json)) {
        html += '<a href="' + json + '" class="json-string" target="_blank">"' + json + '"</a>';
      } else {
        json = JSON.stringify(json);//保留字符串中的\n等
            let len = json.length -1;
            if (json.indexOf("\"") ===0 && json.lastIndexOf("\"") ===len) {
                html += '<span class="json-string">' + json + '</span>';
            } else {
                html += '<span class="json-string">"' + json + '"</span>';
            }
      }
    }

效果:

5、遇到问题三:

格式化后,可以点击左侧的三角进行折叠,这时该如何获取<pre>节点下的原始json数据?

1)json-viewer原理:

从源码可以看到json-viewer格式化展示json数据的原理是,将json数据结构解析,放到<ul><li>中,对于每个ul节点可以进行toggle操作,从而实现了折叠效果。折叠后,json-viewer会增加一个<a>标签,记录折叠的字节点个数,如下:

2)如何获取纯文本数据?

在jquery中,获取“容器”中的内容有两种方式:html()和text(),前者返回的数据中包括html标签,后者获取的是纯文本数据。text()方法的原理是,使用正则表达式,去除所有html标签。

function delHtmlTag(str) {
      return str.replace(/<[^>]+>/g,"");//去掉所有的html标记
}

3)json-viewer格式化json后如何获取纯json数据?

我们知道,当折叠互后json-viewer会增加<a>标签,即使使用text()方法获取到纯文本数据,这里面也包含了“n items”的字符串,那么该如何去除掉这些字符串呢?

思路:使用jquery拷贝<pre>节点,然后remove那些折叠的节点数据(<a href="" class="json-placeholder">2 items</a>)

    $("#format_btn").click(function(){
        var my_json_val = $("#json-display").clone(false);
        my_json_val.find("a.json-placeholder").remove();
        var json_val = my_json_val.text();
        if(json_val){
            try {
                var jsonObj = JSON.parse(json_val);   //把json字符串转为json对象
                $("#json-display").jsonViewer(jsonObj,{withQuotes: true});
            } catch(err) {
                $("#json-display").html(json_val+"<br><font color='red'>"+err.message+"</font>");
            }
        }
    });

6、如何让<pre>保持一个初始高度,并随着内容增加而变化?

可以使用min-height属性。https://blog.csdn.net/u013063153/article/details/52424255

Guess you like

Origin blog.csdn.net/liuxiao723846/article/details/118788566