比如我有这样一个 JSON
{
"pages": ["pages/index/index"],
"subpackages": [
{
"name": "A",
"pages": ["innerModule/pages/index/index"]
},
{
"name": "B",
"pages": ["innerModule/pages/index/index"]
}
]
}
需要实现一个函数找到 subpackages 下面 name === "xxx" 的 object ,然后替换当前的 object ,没有找到就 push 到 subpackages
使用 JSON.parse 很简单,但是会丢失格式信息,导致在 CI 中产生额外的 diff ,有什么很好处理这种场景的 AST 库推荐也行
1
justdoit123 2023-02-11 16:58:44 +08:00 1
预期的情况有两种:
1. 当你需要改动的时候,一定会产生 diff 2. 如果没有改动,则不能产生 diff 我的方案:直接用 JSON.parse/stringify 。你说的那种情况应该只有在原本的 JSON 字符串不是用 JSON.stringify 的情况下会产生。你可以先统一把已存在的文件全部重新格式化一遍,后续就不会产生 diff 。 |
2
bagel 2023-02-11 17:01:03 +08:00
key 排个序不就好了
|
3
molvqingtai OP @mistkafka 我只想有改动的字段产生 diff ,因为一些流程的原因,没办法吧整个文件全部 parse 再 format 一遍
|
4
klo424 2023-02-11 17:10:55 +08:00 1
|
5
klo424 2023-02-11 17:12:00 +08:00 1
|
6
klo424 2023-02-11 17:13:20 +08:00 1
他的锚点不好用,重发[笑哭]
console.log(JSON.stringify({ a: 2 }, null, " ")); /* { "a": 2 } */ console.log(JSON.stringify({ uno: 1, dos: 2 }, null, "\t")); /* { "uno": 1, "dos": 2 } */ |
7
molvqingtai OP @klo424 先 parse => stringify , 现在的问题是在 pasre 处就丢失格式信息了
|
8
tool2d 2023-02-11 17:18:25 +08:00 1
这种情况适合用 line parse 功能。
先把{"name": "A" .. }这个对象片段包含的连续行提取出来,别的行号内容都保留下来。 只序列化和反序列化这一小部分的文件内容,然后再拼装输出一个完整文件。相当于自己手动局部对象 JSON.parse/stringify ,而不是全局。 |
9
zictos 2023-02-11 17:19:55 +08:00 1
chatgpt 的答案能参考吗?
推荐使用 jsonc-parser 库,它可以解析带注释的 JSON ,然后根据需要更新 JSON 对象并生成新的 JSON string 。下面是一个示例代码,可以实现题目要求的功能: const { parseTree, findNodeAtLocation, applyEdits, modify } = require("jsonc-parser"); function updatePackage(jsonStr, packageName, packageData) { const ast = parseTree(jsonStr); const subpackagesNode = findNodeAtLocation(ast, ["subpackages"]); const packageIndex = subpackagesNode.children.findIndex( (child) => findNodeAtLocation(child, ["value", "name"]).value === packageName ); if (packageIndex !== -1) { const packageNode = subpackagesNode.children[packageIndex]; const edits = modify(jsonStr, packageNode.offset, packageNode.length, JSON.stringify(packageData)); return applyEdits(jsonStr, edits); } else { const edits = modify(jsonStr, subpackagesNode.offset + subpackagesNode.length - 1, 0, `,${JSON.stringify(packageData)}`); return applyEdits(jsonStr, edits); } } const jsonStr = `{ "pages": ["pages/index/index"], "subpackages": [ { "name": "A", "pages": ["innerModule/pages/index/index"] }, { "name": "B", "pages": ["innerModule/pages/index/index"] } ] }`; console.log(updatePackage(jsonStr, "C", { name: "C", pages: ["pages/C/index"] })); 在上面的代码中,updatePackage 函数接收一个 JSON string 、需要更新的包名和包数据。它首先使用 jsonc-parser 解析 JSON string ,然后在 AST 中查找 subpackages 节点。然后它在 subpackages 的子节点中查找与给定包名匹配的节点,如果找到了就将它替换为给定的包数据,否则就将包数据添加到 subpackages 的末尾。最后,它将生成的新 JSON string 返回。 由于使用 jsonc-parser 解析 JSON string 时可以保留格式信息,因此在 CI 中就不会产生额外的 diff 了。 |
10
klo424 2023-02-11 17:24:57 +08:00
@molvqingtai #7 你好像没看懂我什么意思?你看#6 的代码,stringify 之前是没有格式的,加了后面的参数就有了格式。你手写的格式跟他一样就行了。
|
11
molvqingtai OP @zictos 感谢,我试试这个代码,今天也用了 V 站上面免登录的 chatgpt ,问了半天也没问出你这样的结果,难道需要走什么流程
|
12
klo424 2023-02-11 17:29:17 +08:00 1
你试一下好吧,根本不需要什么库[笑哭]
console.log(JSON.stringify({uno:1,dos:[2,3],dns:{wf:{bbq:'5'},aec:4}}, null, "\t")) { "uno": 1, "dos": [ 2, 3 ], "dns": { "wf": { "bbq": "5" }, "aec": 4 } } |
13
klo424 2023-02-11 17:29:49 +08:00
v2 把格式过滤掉了,发不出格式。
|
14
molvqingtai OP @klo424 感谢你的热情,但是我不能把已有的 JSON 都格式化一遍,而且输入的 object 格式也不一定和原 JSON 一致,总结就是想达到就像手动编辑一样的 diff 效果
|
15
molvqingtai OP @klo424 v2 支持 markdown ....
|
16
klo424 2023-02-11 17:35:08 +08:00 via iPhone
评论不支持
|
17
klo424 2023-02-11 17:40:25 +08:00 via iPhone
那我觉得你只能用正则写了,其他的插件也会有自己的格式,都有相同的问题。
|
18
zictos 2023-02-11 17:43:38 +08:00
@molvqingtai #11 别人做的是第三方的,调用 api 的,api 的跟目前官方网页版不一样,一点都不智能一点都不好用。反正我试了基本很多答案都没法用,而官方网页版每次的回答都很智能很有针对性
|
19
lisongeee 2023-02-11 21:30:53 +08:00 1
<script src="https://gist.github.com/lisonge/51f6a7e6118a3412ecc226d20ea4fa0d.js"></script>
实现了找到替换的功能,使用的库是 acorn(解析 ast 获取位置) 和 magic-string(更新字符) |
20
lisongeee 2023-02-11 21:39:08 +08:00 1
|
21
caotian 2023-02-12 21:22:59 +08:00 1
试试 json patch
|
22
libook 2023-02-13 10:25:15 +08:00 1
取决于你原 JSON 文本是如何产生的。
如果你可以控制原 JSON 文本的生成过程,你可以给字段名进行递归排序,然后利用 stringify 的第 2 、3 位参数(去看一下 stringify 的文档)来格式化生成。后续修改也用相同方式处理,就可以得到除了修改部分一致的 JSON 文本。这个概念通常被称为 json stable stringify ,有一些现成的库可以用。 如果你不能控制原 JSON 文本的生成过程,我没有想到什么好方法,可能只能用正则去匹配和修改文本中要改的那部分了。 |
23
molvqingtai OP 感谢大家回复,已使用 #9 的 chatgpt 答案,改吧改吧解决了
|