惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LangChain Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
M
MIT News - Artificial intelligence
IT之家
IT之家
The Register - Security
The Register - Security
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
The GitHub Blog
The GitHub Blog
博客园 - 聂微东
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
腾讯CDC
W
WeLiveSecurity
博客园_首页
A
About on SuperTechFans
G
Google Developers Blog
博客园 - 叶小钗
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
量子位
Google DeepMind News
Google DeepMind News
博客园 - 【当耐特】
aimingoo的专栏
aimingoo的专栏
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 三生石上(FineUI控件)
N
News | PayPal Newsroom
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
AI
AI
TaoSecurity Blog
TaoSecurity Blog
P
Proofpoint News Feed
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 司徒正美
www.infosecurity-magazine.com
www.infosecurity-magazine.com
J
Java Code Geeks
Hacker News - Newest:
Hacker News - Newest: "LLM"
爱范儿
爱范儿
S
SegmentFault 最新的问题
Martin Fowler
Martin Fowler
Vercel News
Vercel News
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
H
Heimdal Security Blog
N
News and Events Feed by Topic

Anran758's blog

Promise 与异步编程 数据结构实践 MySQL 实践 组件通信: EventBus 的原理解析与应用 Redux 食用指南 计算机网络原理笔记 Accessibility Parsing 无障碍页面分析 软件工程笔记 JavaScript 实现二叉树 闭包与链式设计的使用示例 React 知识回顾 (优化篇) React 知识回顾 (使用篇) Hexo 常见问题解决方案 React vs Vue webpack + Travis CI 自动部署项目应用 从零构建 webpack 脚手架(基础篇) Flexbox 布局实际用例 Flexbox 布局入门 Hexo blog 的升级与同步方案
将 JSON 数据格式输出至页面上
本文作者: anran758 · 2019-08-24 · via Anran758's blog

JSON 是一种轻量级的数据交换格式,它有键值对集合(js 中的对象)和数组两种结构。JSON是一个通用的格式,在前后端语言中都能跟该 JSON 打交道。

有时候我们需要将 JSON 格式输入至页面展示的需求,其中还需要保持一定的索引,那么该如何实现呢?

使用

我们将对象转为 JSON 字符串时会经常使用 JSON.stringify 这个 API,其实该方法就内置有格式化的参数:

1
2
3
4
5
var userInfo = {name: 'anran758',github: 'https://github.com/anran758'};
var info = JSON.stringify(userInfo, null, 2);

console.log(info);

在上面的代码中,我们第一个参数(value)传入了一个需要序列化的对象。第二个参数是replacer,用以对属性转换和处理,由于我们不需要额外的处理,因此传入一个null;第三个参数则是空格索引的个数,封顶是100或不传则没有空格。

在控制台打印出信息后,我们可以看的出来格式化的数据是带换行符,并且有缩进的格式。接下来我们就要考虑如何输出到页面中。

输出

只要学过HTML的朋友都知道,我们直接将数据输入至HTML中,空格缩进会被浏览器给忽略掉的。因此不能输入到 <div> 中。这时候又想到,JSON格式实际上也算是代码的一种,那能不能输入至雷士代码块的标签中呢?答案是可以的。

HTML 中有两个标签可以展示源代码: <pre><code> 。它们之间不同之处在于:

  • <pre> 表示预定义格式文本,按照原文件中的编排,以等宽字体的形式展现出来,文本中的空白符(比如空格和换行符)都会显示出来
  • <code> 则是呈现一段计算机代码,它以浏览器的默认等宽字体显示,但并不一定会完整呈现原来的格式

这些标签知识实际上算是比较冷门的知识,或许远古的面试题会考这种知识点,平时很少会遇到。但是如果你经常使用markdown的话,那么这些标签在markdown中有不同的别名:

1
2
3
比如 markdown 语法中的 ``,实际上等同于 <code> 标签。实际作用是短代码块标签

而 markdown 语法中的长代码块就等同于 `<pre>` 标签,不同的博客或者网站的应用中还可以对 `<pre>` 加类名,用以展示不同的语言的语法高亮。

通过三者之间的对比可以看出,只有 <pre> 才是符合我们需求的。

确定好展示的方式后,就可以考虑进一步扩展格式化的功能。比如对象中还有属性是 JSON 字符串的话,咱也进一步的解析,直至最底层。想实现这种功能需要编写一个递归函数,考虑如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const isPlainObject = (v) => Object.prototype.toString.call(v) === "[object Object]"
const isString = (v) => Object.prototype.toString.call(v) === "[object String]"







function formatJsonStrAsObj(sample) {
let temp = sample;

if (isString(temp)) {

try {
temp = JSON.parse(temp);
} catch (ex) {

return sample;
}
}

if (isPlainObject(temp)) {
temp = { ...temp };

Object.keys(temp).forEach(key => {
const item = temp[key];


if (isString(item) || isPlainObject(item)) {
temp[key] = formatJsonStrAsObj(item);
}
});
}

return temp;
}








function formatJSONIndnt(sample, indnt = 2) {
const newSample = formatJsonStrAsObj(sample);

if (isString(newSample)) return newSample;

try {
return JSON.stringify(newSample, null, indnt);
} catch (ex) {
return newSample.toString();
}
}

const info = JSON.stringify({
name: 'anran758',
avatar: 'https://xxx',
detail: JSON.stringify({
desc: 'some description',
level: 2,
})
})
const data = formatJSONIndnt(info);
console.log(data);


输入

上文讲了如何将数据输出至页面,以及扩展格式化功能的示例。接下来讲解输入方面的应用。

当用户从别的地方复制数据想粘贴至输入框时,可以在输入框上设置监控事件,触发事件后尝试帮用户格式化数据,示例代码如下:

1
2
3
4
<div class="container">
<pre class="preview pre"></pre>
<textarea class="textarea"></textarea>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const info = JSON.stringify({
name: 'anran758',
avatar: 'https://xxx',
detail: JSON.stringify({
desc: 'some description',
level: 2,
})
})
const data = formatJSONIndnt(info);

const textarea = document.querySelector('.textarea');
const preview = document.querySelector('.pre');

preview.innerHTML = data;
textarea.addEventListener('paste', (e) => {

e.preventDefault();
const value = (e.clipboardData || window.clipboardData).getData('text');


e.target.value = formatJSONIndnt(value, 2);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
body {
display: flex;
margin: 0;
justify-content: center;
align-items: center;
padding: 0 10px;
box-sizing: border-box;
min-height: 100vh;
}

.container {
display: flex;
width: 100%;
}

.preview {
flex: 1;
margin-bottom: 20px;
padding: 20px;
background: #f5fcff;
border: 1px solid #d3eeff;
border-radius: 3px;
margin: 0;
}

.textarea {
flex: 1;
margin-left: 20px;
padding: 10px;
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
monospace;
}

.preview + .preview {
margin-left: 10px;
}

参考资料