Home > front end >  JSON.stringify() replacer function and namespace
JSON.stringify() replacer function and namespace

Time:11-16

I am trying to highlight some part of a JSON in Javascript, found in the following const namespace using JS JSON.strigify() second parameter replacer. So when the key is equal to the namespace, it increase the index in the namespace to progress. Finally, I am surrounding the value with keys 0 and Z.

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)

The problem is not following the right path. In the above example, it goes to styles.elements.heading.typography.fontSize instead of styles.typography.fontSize.

Any idea ?

CodePudding user response:

If you use a replacer, it is called recursively on the modified object that the replacer returns.

If the replacer is inserting new properties into the tree, this makes it difficult to keep track of the position in the tree that the current invocation of the replacer is working on.

You can do this with objects instead:

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));

Note that I've replaced '0' with 'A', since '0' would be always be ordered as the first property in the object, rather than immediately preceding the desired property.

  • Related