HTML显示
<!-- html template -->
<pre id="jsonResult" class="json-result"></pre>
/* less/scss */
.json-result {
border: 0;
padding: 5px;
background-color: #fff;
font-size: 12px;
.string {
color: green;
}
.number {
color: darkorange;
}
.boolean {
color: blue;
}
.null {
color: magenta;
}
.key {
color: red;
}
}
格式化
/**
* JSON 格式化
* @param {string} json 对象或字符串
*/
export function syntaxHighlight(json) {
if (!json || json.length === 0) {
return '';
}
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, 2)
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function (match) {
let cls;
if (/^"/.test(match)) {
cls = /:$/.test(match) ? 'key' : 'string'
} else if (/true|false/.test(match)) {
cls = 'boolean'
} else if (/null/.test(match)) {
cls = 'null'
} else {
cls = 'number'
}
return '<span class="' + cls + '">' + match + '</span>'
})
}
// call
document.getElementById('jsonResult').innerHTML = syntaxHighlight(THE_JSON_OBJECT);
核心点
核心点就在这个正则表达式:
("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)
(
"
( \\u[a-zA-Z0-9]{4} | \\[^u] | [^\\"] )*
"
(\s*:)? | \b
(true|false|null)
\b | -?
\d+
(?:\.\d*)?
(?:[eE][+-]?\d+)?
)
模式匹配
用到了不常见的JS正则表达式模式匹配(来自博客园)
- (?:pattern) 非获取匹配,匹配 pattern 但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry | industries”更简略的表达式。
- (?=pattern) 非获取匹配,正向肯定预查,在任何匹配 pattern 的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3 .1 ”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
- (?!pattern) 非获取匹配,正向否定预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000 )”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
- (?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“ 2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
- (?<!pattern) 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“ 3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
边界匹配
- \b只能匹配字母、数字、汉字、下划线
- \b就近匹配,比如\bAB 匹配A,而AB\b 匹配B;但如果只写一个\b或者在两个字母、数字、汉字、下划线之间有\b时就在所有字符或者两个字母、数字、汉字、下划线之间所有字符去逐个匹配
举例:
/\bnice\b/.test("It's a nice day today.") // true
/\bnice\b/.test("It' nicely.") // false