简体   繁体   中英

Creating a nested JSON object dynamically?

I am almost there with this but cannot seem to get this functionality going as planned.

I have json 'jsonData' it contains formula of different terms

"jsonData":{
            "a" : "b + c",
            "b" : "d + e",
            "d" : "h + i",
            "c" : "f + g"
        }

What I am trying to do is to have a function pass one arguments 'mainItem'(ie. one of the key in 'jsonData' for example a in 'jsonData'). Within this function it will get the formula from the json data(for example a is the 'mainitem' and b + c is the formula) and check the dependency of child component of the formula ie it will check whether b and c have any dependency down the line in json data. If it has any dependency it will be added as a child component to the parent for example if b have a formula in json data. b will be added as the 'mainitem' in the child component of the parent 'mainitem' a . At the end of the code, this is what I would like to get.

{
mainitem : "a",
formula : "b+c",
childComponent: {
                 mainitem: "b",
                 formula : "d+e",
                 childcomponent: {
                                  mainitem: "d",
                                  formula : "h+i"
                                  }
                 },
                 {
                 mainitem: "c",
                 formula : "f+g"
                 },
}

The issue is that I am able to create the parent object. But I have no idea how to create the child component for the parent and If the child component have sub child it will also embedded as the child of the child component and so on. It is like a parent child hierarchy series

function getJson(mainItem) {
  var json = {};
  json['mainitem'] = mainItem;
  $.each(jsonData, function(key, value){
    if(mainitem == key){
      json['formula'] = value;
    }
  })
}

Any insight into this would highly be appreciated. Thank you.

You need/could to write a recursive function that splits up the "formula" into each composing component/item and then check each component/item for their dependencies.

Here is a solution for you: http://jsfiddle.net/mqchen/4x7cD/

function getJson(item, data) {

    if(!data["jsonData"].hasOwnProperty(item)) return null;

    var out = {
        mainItem: item, 
        formula: data["jsonData"][item]
    };

    // Break up formula
    var components = out.formula.split(" ");

    for(var i = 0; i < components.length; i++) {
        var child = getJson(components[i], data); // Recursive call to get childComponents
        if(child !== null) {
            out["childComponent"] = out["childComponent"] == undefined ? [] : out["childComponent"];
            out["childComponent"].push(child);
        }
    }

    return out;
}

// Call it
getJson("a", data)

Note : It does not consider circular dependencies, ie if you have a: "b + c", b: "d + a" .

This is a dependency problem. I can already tell you ahead of time that you will need to figure out a way to handle circular dependencies (you don't want to get thrown into an infinite loop/recursion when trying to generate the output). Let's go through the basic algorithm. What are some things we need?

  1. We need a way to parse the formulas so that they're meaningful. For this example, I'm gonna assume that we'll get an input that's of the form a + b + c , where I only expect the item and + to delimit each item.
  2. We need a way to recurse down an item's dependencies to create nested childcomponent s.

     // assuming jsonData is available in this scope function getStructure (elem) { elem = $.trim(elem); // handling an element that doesn't exist in jsonData if (!jsonData[elem]) { return { 'mainitem': elem, 'formula': 'none' // or whatever you want to put }; } var result = {}, formula = jsonData[elem], children = formula.split('+'), i; result['mainitem'] = elem; result['formula'] = formula; // or however you want to store the child components result['childComponent'] = []; for (i = 0; i < children.length; i += 1) { result['childComponent'].push(getStructure(children[i])); } return result; } 

Yeah this is some sort of building Syntax Tree as in classic parser/compiler problem.

Any ways I have written this simple recursive function that does what you want. Though if your goal is to build some sort of parser then you must think of following parser / compiler building principles since that will keep things manageable and graspable once functions start growing.

    function getJson(mainitem,outjson)
    {
        formula = jsonData[mainitem]; 
        outjson.mainitem = mainitem;

        if (formula != null)
        {
            outjson.formula = formula;
            var firstItem = formula.toString().charAt(0);
            var secondItem = formula.charAt(formula.length - 1);                
            outjson.firstchild = {};
            outjson.secondchild = {};
            getJson(firstItem, outjson.firstchild);
            getJson(secondItem, outjson.secondchild);
        }
    }

What all you have to do is to create an empty object and pass it to getJson() along with the operand in problem ie mainitem:

    var outjson = {};
    getJson("a", outjson);

I have used JSON library to convert outjson object to JSON text.

Also I have logged this outjson so that you can examine it in the embedded firebug lites' Console window.

Find it at JSFiddle .

There is approved answer already but here are my 5 cents.

as @Mahesha999 said you need to build "Syntax Tree as in classic parser/compiler". For some theory + examples look at those videos

They are focused on antlr but also contains a lot theory about parsers. Also antlr have javascript plugin that can be used.

I think it's better than any expression evaluation.

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