在嵌套的JSON对象javascript中不更新浅拷贝

时间:2015-07-27 05:12:06

标签: javascript json angularjs

我有一个嵌套的JSON对象:

var jsonObj = 
{ "level1" : 
      { "status" : true,
        "level2" : {} // and it has the same format and can go to level3, 4, etc
       }
}

我想做的很简单,我想进入Level2,并为其添加一个新的Level3对象。 基本上我想在下面执行以下代码,但由于级别是动态的,我需要一个遍历我的对象的函数。

obj.Level1.Level2.Level3 = { 'status' : true}

这是我的代码片段:

function updateStatusForLevel(nestedObj, categoryHierarchy){
        // categoryHierarchy that is passed = ['Level1', 'Level2', 'Level3']; 
        var obj = nestedObj;

        angular.forEach(categoryHierarchy, function(value, key){
            obj = obj[value];


            if (key === categoryHierarchy.length - 1 && angular.isUndefined(obj)){
                 obj[value] = {}; // I want to add 'Level3' = {}
            }
        });
        obj.status = 'true'; // and finally, update the status 
        console.info("my original obj is " + JSON.stringify(nestedObj));
    }

然而,好像我错过了一些东西。如果我这样做,我的原始nestedObj仍然与我传入的相同(它没有更新,只更新obj对象。我相信这应该是一个非常简单的代码,遍历嵌套的JSON对象为什么浅层副本没有更新原始对象?

2 个答案:

答案 0 :(得分:1)

也许就像这样

function updateStatusForLevel(nestedObj, categoryHierarchy){
        // categoryHierarchy that is passed = ['Level1', 'Level2', 'Level3']; 
        if(categoryHierarchy.length) {
             var shifted = categoryHierarchy.shift();
             nestedObj[shifted] = {status: true};
             return updateStatusForLevel(starter[shifted], categoryHierarchy);
       } else {
             return nestedObj;
       }
}

然后调用updateStatusForLevel(nestedObj, ['level1', 'level2', 'level3'])会将nestedObj修改为

level1: Object
    level2: Object
        level3: Object
            status: true
        status: true
    status: true

请注意,这个答案并不聪明,所以更好地使用plnkr或更好的asnwer,但是现在,请在浏览器开发控制台中试试

答案 1 :(得分:0)

由于您只想从嵌套对象的某个路径添加值,那么如何创建可以执行此操作的通用函数,而不是创建自定义函数。我创建了一个名为helper的工厂,它可以是您稍后可能要添加的辅助函数的集合。

<强> DEMO

<强> JAVASCRIPT

  .factory('helper', function() {

    var helper = {};

    helper.set = function(object, path, value) {

      // save reference of an object
      var reference = object,
          // last key n the path
          lastKey;

      path = angular.isArray(path)? path: // set as an array if it is an array
          angular.isString(path)? path.split('.'): // split the path as an array if it is a string
          false; // set to false and do nothing if neither of the conditions above satisfies

      // check if path is truthy
      if(path) {

        // get the last key of the path
        lastKey = path.pop();

        // reduce the references until all the remaining keys
        reference = path.reduce(function(reference, key) {

          // check if the current object reference is undefined
          if(angular.isUndefined(reference[key])) {
            // set current object reference as an object if it is undefined
            reference[key] = {};
          }

          // return the current object reference for the next iteration
          return reference[key];

        }, reference); 

        // set the last object reference for the value
        reference[lastKey] = value;

      }

      return object;

    };

    return helper;

  })

  .run(function(helper) {

    var object1 = {},
        object2 = {},
        object3 = {},

        object4 = { 
          "level1" : { 
            "status" : true,
            "level2" : {}
          }
        };

    helper.set(object1, 'z.k.v.q', { status: false });
    // object1 = { z: { k: { v: { q: { status: false } } } } }
    console.log(object1);

    helper.set(object2, 'a.e.i.o.u', { status: true });
    // object2 = { a: { e: { i: { o: { u: { status: true } } } } } }
    console.log(object2);

    helper.set(object3, ['hello', 'world'], { status: undefined });
    // object3 = { hello: { world: { status: undefined } } }
    console.log(object3);

    helper.set(object4, 'level1.level2.level3', { status: true });
    // object4 = { status: true, level1: { level2: { level3: { status: true } } } }
    console.log(object4);

  });

或者,您可以使用lodash进行此操作,并且您可以执行更多对象,数组和集合操作。您应该查找的lodash函数为_.set()

<强> DEMO

<强> JAVASCRIPT

  .service('_', function($window) {
    // you can add mixins here
    // read more about lodash if you
    // want to customize data manipulation
    return $window._;
  })

  .run(function(_) {

    var object1 = {},
        object2 = {},
        object3 = {},

        object4 = { 
          "level1" : { 
            "status" : true,
            "level2" : {}
          }
        };

    _.set(object1, 'z.k.v.q', { status: false });
    // object1 = { z: { k: { v: { q: { status: false } } } } }
    console.log(object1);

    _.set(object2, 'a.e.i.o.u', { status: true });
    // object2 = { a: { e: { i: { o: { u: { status: true } } } } } }
    console.log(object2);

    _.set(object3, ['hello', 'world'], { status: undefined });
    // object3 = { hello: { world: { status: undefined } } }
    console.log(object3);

    _.set(object4, 'level1.level2.level3', { status: true });
    // object4 = { status: true, level1: { level2: { level3: { status: true } } } }
    console.log(object4);

  });