I have a small issue with JSON

2019-08-16 04:04发布

问题:

I have to create a menu tree from a JSON.

The JSON looks like this:

[  
    {  
       "For Home Products":[  
          "Menu Free Antivirus",
          "Menu Premium",
          "Menu Internet Security"
       ]
    },
    {  
       "For Business Products":[  
          {  
             "Client/Servers":[  
                "Menu Professional Security",
                "Menu Server Security",
                "Menu Business Security Suite",
                "Menu Endpoint Security"
             ]
          },
          {  
             "Integration":[  
                "Anti-Malware",
                "Antispam SDK (SPACE)",
                "Rebranding & Bundling",
                "Integration Services"
             ]
          },
          "Small Business",
          "Managed Services",
          {  
             "Gateways":[  
                "Menu MailGate",
                "Menu MailGate Suite",
                "Menu AntiVir Exchange",
                "Menu WebGate",
                "Menu WebGate Suite",
                "Menu GateWay Bundle",
                "Menu SharePoint"
             ]
          }
       ]
    }
 ]

The way I tried to solve the problem looks like this:

function setData(data) {
    console.log(data);
    $.each(data, function(key1, value1) {

        $.each(value1, function(key2, value2) {
            var x = document.createElement("ul");
            x.setAttribute("id", key2);
            document.body.appendChild(x);
            $.each(value2, function(key3, value3) {
                // console.log(value3);
                var z = document.createElement("li");
                z.setAttribute("id", value3);
                document.getElementById(key2).appendChild(z);
                console.log(value3);


            })
        })
    })
    return setData;
}

setData(data);

Now, my problem is that the classes are not added correctly. e.g:

 <li id="[object Object]"></li>

I know that the error is because I'm trying to make a class from an object, but I'm trying to solve this problem for two hours now and I can't find the correct way of doing this without hard coding it.

Output

Code Snippet (Run)

var data = [  
    {  
       "For Home Products":[  
          "Menu Free Antivirus",
          "Menu Premium",
          "Menu Internet Security"
       ]
    },
    {  
       "For Business Products":[  
          {  
             "Client/Servers":[  
                "Menu Professional Security",
                "Menu Server Security",
                "Menu Business Security Suite",
                "Menu Endpoint Security"
             ]
          },
          {  
             "Integration":[  
                "Anti-Malware",
                "Antispam SDK (SPACE)",
                "Rebranding &amp; Bundling",
                "Integration Services"
             ]
          },
          "Small Business",
          "Managed Services",
          {  
             "Gateways":[  
                "Menu MailGate",
                "Menu MailGate Suite",
                "Menu AntiVir Exchange",
                "Menu WebGate",
                "Menu WebGate Suite",
                "Menu GateWay Bundle",
                "Menu SharePoint"
             ]
          }
       ]
    }
 ]
function setData(data) {
    //console.log(data);
    $.each(data, function(key1, value1) {

        $.each(value1, function(key2, value2) {
            var x = document.createElement("ul");
            x.setAttribute("id", key2);
            document.body.appendChild(x);
            $.each(value2, function(key3, value3) {
                // console.log(value3);
                var z = document.createElement("li");
                z.setAttribute("id", value3);
                z.innerHTML = value3;
                document.getElementById(key2).appendChild(z);
                console.log(value3);


            })
        })
    })
    return setData;
}

setData(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

回答1:

Your JSON doesn't match the desired output. I've modified the JSON here to match better with your desired output.

Also, the reason why you were getting [Object object] showing up in your code is that you weren't checking to see the type of the values in your each loops. Both an array [] and an object {} will show up as typeof value==='object'. You could also look for typeof value==='string', but in your given example it's really sort of an either/or problem. So not really necessary to do both checks.

recursion might be a better solution to this. Here's an example:

function setData(data, el) {
	if(!el.is('ul')) el = $('<ul/>').appendTo(el);
	$.each(data, function(key, value) {
		if(typeof value==='object') {
			if(typeof key==='string') 
				el = $('<li/>').appendTo(el).text(key);
			setData(value, el);
		}
		else $('<li/>').text(value).appendTo(el);
	});
}

// this JSON matches better with your desired output image
// it appears that integration and gateways are "collapsed"
// which would be a simple styling application. If they
// are in fact empty, you could just remove the children items
// from the JSON.
var newData = [  
    {  
       "For Home Products":[  
          "Small Business",
          "Managed Services",
          "Internet Security"
       ]
    },
    {  
       "For Business Products":[  
          {  
             "Client/Servers":[  
                "Professional Security",
                "Server Security"
             ]
          },
          {  
             "Integration":[  
                "Anti-Malware",
                "Antispam SDK (SPACE)",
                "Rebranding &amp; Bundling",
                "Integration Services"
             ]
          },
          "Small Business",
          "Managed Services",
          {  
             "Gateways":[  
                "Menu MailGate",
                "Menu MailGate Suite",
                "Menu AntiVir Exchange",
                "Menu WebGate",
                "Menu WebGate Suite",
                "Menu GateWay Bundle",
                "Menu SharePoint"
             ]
          }
       ]
    }
 ];

setData(newData, $('body'));

// Original JSON which doesn't match desired output
/*
var data = [  
    {  
       "For Home Products":[  
          "Menu Free Antivirus",
          "Menu Premium",
          "Menu Internet Security"
       ]
    },
    {  
       "For Business Products":[  
          {  
             "Client/Servers":[  
                "Menu Professional Security",
                "Menu Server Security",
                "Menu Business Security Suite",
                "Menu Endpoint Security"
             ]
          },
          {  
             "Integration":[  
                "Anti-Malware",
                "Antispam SDK (SPACE)",
                "Rebranding &amp; Bundling",
                "Integration Services"
             ]
          },
          "Small Business",
          "Managed Services",
          {  
             "Gateways":[  
                "Menu MailGate",
                "Menu MailGate Suite",
                "Menu AntiVir Exchange",
                "Menu WebGate",
                "Menu WebGate Suite",
                "Menu GateWay Bundle",
                "Menu SharePoint"
             ]
          }
       ]
    }
 ];

setData(data, $('body'));
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>



回答2:

The issue is that the levels of your json aren't uniform, so at times you're returning the name you want, and at other times that level is an object, so you're returning the object. You'll need to check for that in your code with something like this:

$.each(value2, function(key3, value3) {
    // console.log(value3);
    if(typeof value3 !== 'object') {
        var z = document.createElement("li");
        z.setAttribute("id", value3);
        z.innerHTML = value3;
        document.getElementById(key2).appendChild(z);
        console.log(value3);
    } else {
        // Go a level deeper in your json.
    }
});

All I did was add the following check in:

if(typeof value3 !== 'object') {
    // If not object.
} else {
    // If object.
}

What the addition above does is check the type of the value3 variable and if it isn't an object, it'll create the li, otherwise you know it is an you can handle it appropriately.