简体   繁体   中英

Better way to map a deep object to new object

This code works for converting the JSON to an object where each name object turns into the key for either its value, or if it instead has its own element object breaks that out and does the same to its contents.

Is there a better way to do this that would also allow for more extensiblity of the JSON schema?
Is there a way I can get it all down to a simpler function that I can pass the first element and have it convert it down to whatever depth the schema goes?

const fs = require('fs');
{
    let scheme = JSON.parse('{"$schema":{"root":{"name":"THINGY","dtd":{"name":"DOCTYPE","value":"something.dtd","commentBefore":["?xml version='1.0'?","Version NULL"]},"ele":{"name":"REPORT","ele":[{"name":"SEGMENT0","ele":[{"name":"NUMBER1","value":""},{"name":"NUMBER2","value":""}]},{"name":"SEGMENT1","ele":[{"name":"RECORD1","ele":[{"name":"NUMBER1","value":""},{"name":"NUMBER2","value":""}]}]},{"name":"SEGMENT2","ele":[]},{"name":"SEGMENT3","ele":[]},{"name":"SEGMENT4","ele":[]},{"name":"SEGMENT5","ele":[]}]}}}}').$schema.root;
    let depth = 0;

    var compiled = {
        [scheme.ele.name]: scheme.ele.ele.map(function(i) {
            if (typeof i.ele != 'undefined') {
                return {
                    [i.name]: i.ele.map(function(k) {
                        if (typeof k.ele != 'undefined') {
                            return {
                                [k.name]: k.ele.map(function(p) {
                                    if (typeof p.ele != 'undefined') {
                                        return {
                                            [p.name]: p.ele
                                        };
                                    } else {
                                        return {
                                            [p.name]: p.value
                                        };
                                    }
                                })
                            };
                        } else {
                            return {
                                [k.name]: k.value
                            };
                        }
                    })
                };
            } else {
                return {
                    [i.name]: i.value
                };
            }
        })
    };
}

console.log(JSON.stringify(compiled, 0, 2));

I should add, this is intended to eventually also apply validation and grab real data when it gets to the string objects.

The output looks like this:

{
    "REPORT": [
    {
        "SEGMENT0": [
        {
            "NUMBER1": ""
        },
        {
            "NUMBER2": ""
        }
        ]
    },
    {
        "SEGMENT1": [
        {
            "RECORD1": [
            {
                "NUMBER1": ""
            },
            {
                "NUMBER2": ""
            }
            ]
        }
        ]
    },
    {
        "SEGMENT2": []
    },
    {
        "SEGMENT3": []
    },
    {
        "SEGMENT4": []
    },
    {
        "SEGMENT5": []
    }
    ]
}

You could destructure the object, get name , ele and value and return a new object with name as key and either an array by mapping the objects of ele or the value .

 const getData = ({ name, ele, value }) => ({ [name]: Array.isArray(ele) ? ele.map(getData) : value }); var scheme = JSON.parse('{"$schema":{"root":{"name":"THINGY","dtd":{"name":"DOCTYPE","value":"something.dtd","commentBefore":["?xml version=\\'1.0\\'?","Version NULL"]},"ele":{"name":"REPORT","ele":[{"name":"SEGMENT0","ele":[{"name":"NUMBER1","value":""},{"name":"NUMBER2","value":""}]},{"name":"SEGMENT1","ele":[{"name":"RECORD1","ele":[{"name":"NUMBER1","value":""},{"name":"NUMBER2","value":""}]}]},{"name":"SEGMENT2","ele":[]},{"name":"SEGMENT3","ele":[]},{"name":"SEGMENT4","ele":[]},{"name":"SEGMENT5","ele":[]}]}}}}').$schema.root, result = getData(scheme.ele); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Nina's answer is cleaner but this looks a bit more like your code so I figured I'd post it anyway.

 let scheme = JSON.parse('{"$schema":{"root":{"name":"THINGY","dtd":{"name":"DOCTYPE","value":"something.dtd","commentBefore":["?xml version=\\'1.0 \\'?","Version NULL"]},"ele":{"name":"REPORT","ele":[{"name":"SEGMENT0","ele":[{"name":"NUMBER1","value":""},{"name":"NUMBER2","value":"1"}]},{"name":"SEGMENT1","ele":[{"name":"RECORD1","ele":[{"name":"NUMBER1","value":"2"},{"name":"NUMBER2","value":""}]}]},{"name":"SEGMENT2","ele":[]},{"name":"SEGMENT3","ele":[]},{"name":"SEGMENT4","ele":[]},{"name":"SEGMENT5","ele":[]}]}}}}').$schema.root; let newScheme = JSON.parse('{"$schema":{"root":{"name":"THINGY","dtd":{"name":"DOCTYPE","value":"something.dtd","commentBefore":["?xml version=\\'1.0 \\'?","Version NULL"]},"ele":{"name":"REPORT","ele":[{"name":"SEGMENT0","ele":[{"name":"NUMBER1","value":"1"},{"name":"NUMBER2","value":"3"}]},{"name":"SEGMENT1","ele":[{"name":"RECORD1","ele":[{"name":"NUMBER1","value":"4"},{"name":"NUMBER2","value":""}]}]},{"name":"SEGMENT2","ele":[]},{"name":"SEGMENT3","ele":[]},{"name":"SEGMENT4","ele":[]},{"name":"SEGMENT5","ele":[]}]}}}}').$schema.root; //Yay, recursion! function mapObj(a, o = {}) { let array = o[a.name] || []; for (let i = 0; i < a.ele.length; i++) { let b = a.ele[i]; array[i] = b.ele ? mapObj(b, array[i]) : { [b.name]: b.value }; } o[a.name] = array; return o; } let obj = mapObj(scheme.ele); console.log(obj); console.log(mapObj(newScheme.ele, obj)); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM