JSON.stringify() 替换函数和命名空间

JSON.stringify() replacer function and namespace

提问人:Romain Guillaume 提问时间:11/16/2022 更新时间:11/16/2022 访问量:227

问:

我正在尝试突出显示 Javascript 中 JSON 的某些部分,在以下 const 中使用 JS JSON.strigify() 第二个参数找到。因此,当键等于命名空间时,它会增加命名空间中的索引以进行进度。最后,我用键 0 和 Z 将值括起来。namespacereplacer

const dataTree = {
    "styles": {
        "elements": {
            "heading": {
                "typography": {
                    "fontFamily": "Volkorn",
                    "fontSize": "16px"
                },
            },
        },
        "typography": {
            "fontFamily": "Vollkorn",
            "fontSize": "16px",
            "lineHeight": "1.7"
        }
    }
}

const namespace = "styles.typography.fontSize".split('.')
let i = 0

const replacer = (k, v) => {
    if(namespace[i] === k){
        i++
        if(i === namespace.length-1){
            if(Object.keys(v).includes(namespace.at(-1))){
                v[0] = 'before' 
                v["Z"] = 'after' 
                return v
            }
        }
    }
    if(v["Z"]) {
        delete v["Z"]
        delete v[0]
    } 
    return v
}
const strV = JSON.stringify(dataTree, replacer, 2)

问题在于没有遵循正确的道路。在上面的示例中,它转到 而不是 .styles.elements.heading.typography.fontSizestyles.typography.fontSize

有什么想法吗?

JavaScript JSON 命名空间

评论

0赞 T.J. Crowder 11/16/2022
你说过你想在“一个 JSON”中执行此操作,但你显示的是一个 JavaScript 对象。JSON 是用于数据交换的文本表示法(更多内容请点击此处。如果你处理的是 JavaScript 源代码,而不是处理字符串,那么你就不是在处理 JSON。您是否正在尝试在 JavaScript 对象中执行此操作,然后将其序列化为 JSON?因为使用替换函数很难(也许不可能)做到这一点,但在转换为 JSON 之前很容易做到这一点。
0赞 T.J. Crowder 11/16/2022
同时请显示您期望的结果
0赞 Romain Guillaume 11/16/2022
是的,这是一个 JS 对象。这是 JSON 字符串版本,包括一些特殊键来包围我想突出显示的值。dataTreestrV
0赞 Romain Guillaume 11/16/2022
我期望 stringify 方法能够更精确地控制替换函数,该函数仅提供键和值,但没有路径或命名空间来精确标识正在处理的对象部分。如果你运行它,你会得到与我预期的结果相似的结果。问题是修改而不是.最后,我将进行更改以在转换为 JSON 之前进行更改,因为没有机会检查替换器函数所在的路径。styles.elements.heading.typography.fontSizestyles.typography.fontSize

答:

1赞 Andrew Parks 11/16/2022 #1

如果使用替换程序,则会在替换程序返回的已修改对象上递归调用它。

如果替换程序在树中插入新属性,则很难跟踪替换程序的当前调用正在处理的树中的位置。

您可以改为使用对象执行此操作:

const dataTree = {"styles":{"elements":{"heading":{"typography":{"fontFamily":"Volkorn","fontSize":"16px"}}},"typography":{"fontFamily":"Vollkorn","fontSize":"16px","lineHeight":"1.7"}}};

const namespace = 'styles.typography.fontSize'.split('.');

const replaceAtLocation = (tree, [p,...rest], replacer) => rest.length ?
  Object.fromEntries(Object.entries(tree).map(([k,v])=>k===p ?
    [k,replaceAtLocation(v, rest, replacer)] : [k,v])) : replacer(tree);

const result = replaceAtLocation(dataTree,namespace,tree=>Object.fromEntries(
  Object.entries(tree).flatMap(([k,v])=>k===[...namespace].pop()?
    [['A','before'],[k,v],['Z','after']]:[[k,v]])));

console.log(JSON.stringify(result, null, 2));

请注意,我已将“0”替换为“A”,因为“0”将始终作为对象中的第一个属性排序,而不是紧挨在所需属性之前。

评论

0赞 Romain Guillaume 11/16/2022
好吧,你的答案完全有效。它仍然非常紧凑,我需要一些时间才能理解这一切。谢谢!