Working With Dynamic Multidimensional key-value pairs in JSON

依然范特西╮ 提交于 2020-01-07 03:23:10

问题


Having a thorny problem and only see similar but also simpler solutions on SO.

Is is possible to generate a dynamic key AND dynamic values using JS/JSON?

For instance, let's say I have JSON like this:

{
    "email": "user@someco.com",
    "firstname": "Bob",
    "lastname": "Smith",
    "company": "ACME",
    "custom": {
        "services": [
            {
                "name": "svc1",
                "desc": "abcdefg",
                "selected": "true",
                "status": "None"
            },
            {
                "name": "svc2",
                "desc": "abcdefg",
                "selected": "true",
                "status": "None"
            },
            {
                "name": "svc3",
                "desc": "abcdefg",
                "selected": "false",
                "status": "None"
            },
            {
                "name": "svc4",
                "desc": "abcdefg",
                "selected": "false",
                "status": "None"
            }
        ],
        "fields": [
            {
                "name": "Products",
                "desc": "abcdef",
                "type": "multi",
                "values": [
                    {
                        "name": "Product1",
                        "desc": "abcdef"
                    },
                    {
                        "name": "Product2",
                        "desc": "abcdef"
                    }
                ],
                "services": [
                    "svc1",
                    "svc2",
                    "svc3"
                ]
            },
            {
                "name": "Wines",
                "desc": "abcdef",
                "type": "multi",
                "values": [
                    {
                        "name": "Wine 1",
                        "desc": "abcdef"
                    }
                ],
                "services": [
                    "svc4"
                ]
            },
            {
                "name": "Fruits",
                "desc": "abcdef",
                "type": "multi",
                "values": [
                    {
                        "name": "Fruit 1",
                        "desc": "abcdef"
                    },
                    {
                        "name": "Fruit 2",
                        "desc": "abcdef"
                    }
                ],
                "services": [
                    "svc4"
                ]
            }
        ]
    }
};

I need to go into the fields and for each field (products, wines, fruits) see if a given service is contained within so that I can go back and generate a product or wine or fruit for each service that requires it. But I don't want to repeat the services names more than once. The resulting JSON should look something like this:

{"svc1":["Products"], "svc2":["Products"], "svc3":["Products"], "svc4":["Fruits", "Wines"]} 

The hope would be that to generate a dynamic list in Angular I can just turn and loop back through this JSON, pulling out the values for each product, fruit, wine, whatever.

I've been trying a lot of nested for loops and the like but whenever I get more than one layer down the dynamism seems to stop. I'm guessing that for this to work I need to move between JS Objects and JSON?

Right now I'm trying something like this, which isn't quite working, stringify or no. And maybe I'm flip-flopping too much between JSON and JS Objects:

var outObj = [];    

var fieldItems;
        $.each(jsonObj.custom.fields, function(key, item) {
            fieldItems = item;
            fieldItems.name = item.name;
            $.each(fieldItems.services, function(key, item) {
                var serviceName = item;
//check to see if the serviceName already exists
                if (outObj.indexOf(serviceName) > -1) {
                outObj.serviceName.push(fieldItems.name);
            } else {
                outObj.push(serviceName);
            }

            });
        });

        JSON.stringify(outObj);
        console.log("outObj " + outObj);

I get "can't read property 'push' of undefined" errors and the like. Seems this should be possible from a single nested loop, but maybe I need to just do two passes? Any other suggestions?


回答1:


To me it sounds like overcomplicated solution. You can use basic array methods of javascript to filter out required structure. I am not sure what profiling_value in the presented snippet, so I started from the object structure in OP

var desiredResult = jsonObj.custom.services.reduce(function(result, service){
  result[service.name] = jsonObj.custom.fields.filter(function(field){
       return field.services.indexOf(service.name) >= 0;
   }).map(function(field){ return field.name; });
  return result;
}, {});

This gives the expected result for mentioned object.

reduce is required to iterate over all services and accumulate result in one object. Then for each service fields are iterated to filter out only those that contain link to this service. And finally list of filtered fields is transformed (map) into list of strings - their names - and inserted into accumulator



来源:https://stackoverflow.com/questions/31975753/working-with-dynamic-multidimensional-key-value-pairs-in-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!