首页 前端知识 手写一个JSON可视化工具

手写一个JSON可视化工具

2024-08-24 23:08:34 前端知识 前端哥 806 707 我要收藏

前言

JSON 平时大家都会用到,都不陌生,今天就一起来实现一个 JSON 的可视化工具。

大概长成下面的样子:

image.png

树展示

相比于现有的一些 JSON 格式化工具,我们今天制作的这个小工具会把 JSON 转为树去表示。其中:

  • 橙色标签表示 key
  • 蓝色标签表示 value
  • 绿色标签表示类型: Number String Object Array Null

左边是一个输入框,右边是一个实时反馈的 JSON 可视化区域。下面来看一下大致的实现思路:

  1. 当输入框的值变化时,使用 JSON.parse 解析值,如果是一个合法的 JSON ,则进行下一步处理;如果不是,则把异常显示出来
  2. 递归把 JSON 对象解析成数组树的结构,主要会包含以下几个 key
    • key 唯一标识,后续用做复制路径
    • title JSON 属性节点 key
    • value JSON 属性节点值
    • isArrayProps 是否是数组的节点
    • children 子节点
    • type 值类型
const handleParse = useCallback(
debounce((value) => {
if (!value) {
return;
}
try {
const res = JSON.parse(value);
setJson(res);
setError(null);
setUpdateKey((key) => key + 1);
setSearchValue("");
} catch (error) {
setJson({});
setError(error);
}
}, 300),
[]
);
useEffect(() => {
handleParse(value);
}, [value]);
复制

value 是输入框的输入值,当输入值变化时,解析 JSON 。获取到新的 JSON 值后,开始递归处理,组装成树结构:

const treeData = useMemo(() => {
const dfs = (json, parentKey) => {
const res = [];
const keys = Object.keys(json);
for (const index in keys) {
const key = keys[index];
const value = json[key];
res[index] = {
key: parentKey ? `['${parentKey}']['${key}']` : `['${key}']`,
title: key,
value: value ? value.toString() : value,
isArrayProps: Array.isArray(json),
children:
typeof value === "object" && value !== null ? dfs(value, key) : [],
type: upperFirst(
value === null
? "null"
: Array.isArray(value)
? "array"
: typeof value
),
};
}
return res;
};
try {
return dfs(json, "");
} catch (error) {
console.log("err", error);
return [];
}
}, [json]);
复制

然后用一个树组件把它渲染出来:

<Tree
showIcon
showLine
titleRender={renderTitle}
key={updateKey}
treeData={treeData}
defaultExpandAll
/>
复制

其中,我们希望自定义渲染树的每一个节点,所以可以实现一个 titleRender 方法:

const renderTitle = (node) => {
return (
<div onClick={() => copy}>
{!node.isArrayProps ? <Tag color="orange">{node.title}</Tag> : ""}
{node.children.length === 0 && node.value ? (
<Tag color="blue">{node.value}</Tag>
) : (
""
)}
<Tag color="green">{node.type}</Tag>
</div>
);
};
复制

image.png

这样就完成了基础的功能逻辑及渲染

搜索

这里我们拓展一个根据关键词搜索的功能,既可以搜索 key ,也可以搜索 value

用到一个 Search 组件来搜集 keyword

<Input.Search
style={{ marginBottom: 8 }}
placeholder="Search"
onChange={(e) => setSearchValue(e.target.value)}
/>
复制

然后当 keyword 变化的时候,去匹配树节点中的属性值,如果匹配到了,就把对应的值标红。

const renderTitle = (node) => {
const highlight = (strTitle) => {
const index = strTitle.indexOf(searchValue);
const beforeStr = strTitle.substring(0, index);
const afterStr = strTitle.slice(index + searchValue.length);
const title =
index > -1 ? (
<span>
{beforeStr}
<span style={{ color: "red" }}>{searchValue}</span>
{afterStr}
</span>
) : (
<span>{strTitle}</span>
);
return title;
};
return (
<div onClick={() => copy}>
{!node.isArrayProps ? (
<Tag color="orange">{highlight(node.title)}</Tag>
) : (
""
)}
{node.children.length === 0 && node.value ? (
<Tag color="blue">{highlight(node.value)}</Tag>
) : (
""
)}
<Tag color="green">{node.type}</Tag>
</div>
);
};
复制

最后实现出来的效果就是这样的;

image.png

复制路径

我不知道大伙有过这样类似的需求:改动一个 json 对象某个 key 对应的值。我之前是有过这样的场景,那是在使用 Lottie 做动画的时候。

我需要对描述 Lottie 动画的 json 文件进行一些修改,但往往这种文件层级非常深,如果不借助一些工具,是很难找到对应的值的路径是什么,找不到路径就很难修改了。

那么我们有了这个工具之后,就很轻松可以通过搜索+复制的方式来找到某个值对应的路径。

<Clipboard text={node.key} onCopy={() => message.success("路径已复制")}>
<div>
{!node.isArrayProps ? (
<Tag color="orange">{highlight(node.title)}</Tag>
) : (
""
)}
{node.children.length === 0 && node.value ? (
<Tag color="blue">{highlight(node.value)}</Tag>
) : (
""
)}
<Tag color="green">{node.type}</Tag>
</div>
</Clipboard>
复制

用一个复制组件包裹树节点,点击的时候把节点的 key 属性复制到粘贴板。

image.png

image.png

这样就可以轻松获取到节点所对应的 key 了。

最后

以上就是本文的全部内容,如果你感兴趣的话,点点关注点点赞吧~

转载请注明出处或者链接地址:https://www.qianduange.cn//article/16760.html
标签
评论
还可以输入200
共0条数据,当前/页
发布的文章

安装Nodejs后,npm无法使用

2024-11-30 11:11:38

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!