问题:
公司遇到了这样一个业务,需要将JSON对象输出到html页面中,点击属性值,并展示这个对象的可访问路径
网上没有找到相关的解决方案,索性自己写了一个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#container {
white-space: pre;
}
#container a {
text-decoration: none;
}
</style>
</head>
<body>
<div id="container"></div>
<input type="text" id="input">
<script>
let obj = {
g: [
{
233: 1
},
{
s: 2
},
{
s123: 2
}
],
a: 'zs',
b: {
c: 12,
d: [1, 2, 3],
e: {
f: 'fff',
a: 'deepa'
}
},
}
// 递归遍历对象里面所有key对应的path, key可以重复。 1为指针指向
var tempKeyPaths = {}
/* {
a: [ 1, 'path1', 'path2' ]
} */
function deepAddPath(obj, parentPath = '') {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
// 获取当前属性路径
const currentPath = parentPath + '.' + key
// 当前元素非数组
if (!Array.isArray(obj)) {
// 判断当前属性,是否设置过存储路径
if (Array.isArray(tempKeyPaths[key])) {
tempKeyPaths[key].push(currentPath)
} else {
//
tempKeyPaths[key] = [1, currentPath]
}
}
// 子元素是一个对象
if (typeof obj[key] == 'object' && typeof obj[key] !== null) {
deepAddPath(obj[key], currentPath)
}
}
}
return obj
}
const res = deepAddPath(JSON.parse(JSON.stringify(obj)))
// 正则拼接,匹配对象key值 /(a | b | c):/
const temp = Object.keys(tempKeyPaths).join('|')
const pattern1 = new RegExp('\"\(' + temp + '\)\":', "gi");
console.log(pattern1)
// 序列化对象,制表符进行缩进
const ss = JSON.stringify(res, null, '\t').replace(pattern1, function (key) {
// 去除:号
key = key.slice(0, -1)
// 去除序列化后的“”, 获取属性指针表
let tempArray = tempKeyPaths[key.slice(1, -1)];
// tempArray[0] 为属性指针指向
let curentVal = tempArray[tempArray[0]]
// 转换数字属性为中括号访问, obj.123 => obj[123]
curentVal = curentVal.replace(/\.\d+/g, function (path) {
path = path.slice(1)
return `['${path}']`
})
// 指针递增
tempArray[0]++
return `<a href="javascript:void(0)" data-path="${curentVal}" class="pathMap">${key}</a>:`
})
let container = document.querySelector('#container')
let input = document.querySelector('#input')
container.innerHTML = ss
container.addEventListener("click", function (e) {
if (e.target.tagName == "A") {
const path = 'obj' + e.target.getAttribute('data-path')
// console.log(path)
input.value = path
}
});
</script>
</body>
</html>