【问题标题】:Javascript Recursion normalize JSON dataJavascript 递归规范化 JSON 数据
【发布时间】:2017-02-08 21:00:35
【问题描述】:

我有一个 json 响应,我想通过递归和减少来简化这个 json 数据。我写了一个函数把我卡在了这一点上。我想删除所有数据元素并创建一个没有数据名称的新对象。

我的json数据是这样的

[
    {
        "city": {
            "data": {
                "id": 649442,
                "country_id": 54,
                "state_id": 682,
                "city_name": "Prague",
                "state_name": "Praha"
            }
        },
        "country": {
            "data": {
                "id": 54,
                "data": {
                    "country_name": "Czech Republic",
                    "short_country": "CZ",
                    "olympic_code": "CZE"
                }
            }
        }
    }
]

我的功能在这里:

function normalizeData(object) {
  return Object.keys(object).reduce((finalObject, objectKey) => {
    if (object[objectKey] && object[objectKey].data) {
      finalObject[objectKey] = object[objectKey].data;
      if (Array.isArray(finalObject[objectKey].data)) {
        finalObject[objectKey] = object[objectKey].data.map(item => {
          return normalizeData(item);
        });
      } else {
        finalObject[objectKey] = normalizeData(object[objectKey].data);
      }
    } else {
      finalObject[objectKey] = object[objectKey];
    }
    return finalObject;
  }, {});
};

我仍然在获取数据对象。那么我在哪里犯错了。或者有更好的方法吗?

【问题讨论】:

  • 欢迎来到苏谭!为了清楚起见,您希望删除某些键并获得新的、已清理的对象。正确的?但是id=54 的反对应该怎么办?
  • 是的,我想避免输入数据,所以 id: 54 应该是这样的 { "country": { "id": 54 } }
  • 如果您可以举一个输入和预期输出的示例,这将有所帮助。谢谢。

标签: javascript json recursion reduce


【解决方案1】:

我发现了我的错误。我在对象顶部有一个数组:) 所以我修复了这样的代码。

export function normalizeData(object) {
  return Object.keys(object).reduce((finalObject, objectKey) => {
    if (object[objectKey] && object[objectKey].data) {
      finalObject[objectKey] = object[objectKey].data;
      if (Array.isArray(finalObject[objectKey].data)) {
        finalObject[objectKey] = object[objectKey].data.map(item => {
          return normalizeData(item);
        });
      } else {
        finalObject[objectKey] = normalizeData(object[objectKey].data);
      }
    } else {
      finalObject[objectKey] = object[objectKey];
    }
    return finalObject;
  }, {});
}

export function normalizeArray(array) {
  return array.map(object => {
    return normalizeData(object);
  })
}

【讨论】:

    【解决方案2】:

    这是一个没有reduce() 的解决方案,它检查对象属性是否未被继承(hasOwnProperty()),并对作为对象本身的每个属性进行递归。如果属性键是data,那么所有的值都会被复制到父对象,然后data 键会从对象中删除。这就是它变得棘手的地方,因为data 对象本身可以有一个data 属性,因此必须检查这一点并且需要应用双重递归。

    var jsonStr = `{
        "city": {
            "data": {
                "id": 649442,
                "country_id": 54,
                "state_id": 682,
                "city_name": "Prague",
                "state_name": "Praha"
            }
        },
        "country": {
            "data": {
                "id": 54,
                "data": {
                    "country_name": "Czech Republic",
                    "short_country": "CZ",
                    "olympic_code": "CZE"
                }
            }
        }
    }`;
    
    var jo = JSON.parse(jsonStr);
    
    function normalize(obj) {
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (typeof obj[key] === 'object') {
                    if (key === 'data') {
                        // check if data object also has a data property
                        if (obj[key].hasOwnProperty('data')) {
                            // double recursion
                            normalize(obj[key]);
                            normalize(obj);
                        }
                        else {
                            // copy all values to the parent
                            // (only if they don't exist in the parent yet)
                            for (var subKey in obj[key]) {
                                if (obj[key].hasOwnProperty(subKey)
                                &&  !obj.hasOwnProperty(subKey)) {
                                    obj[subKey] = obj[key][subKey];
                                }
                            }
                            // remove the data key
                            delete obj[key];
                        }
                    }
                    else {
                        // recursion
                        normalize(obj[key]);
                    }
                }
            }
        }
    }
    
    normalize(jo);
    
    console.log(jo);

    如果您不希望函数修改输入,您可以先使用deep extend 创建对象的副本并返回该副本。

    【讨论】:

    • 好吧,这是一个解决方案,但也是一个高度复杂的函数:没有关注点分离,几乎不可重用。
    • @ftor 是的,但是让它可重复使用也不是太难,不是吗?
    猜你喜欢
    • 2018-04-03
    • 2020-07-09
    • 2016-12-06
    • 1970-01-01
    • 2014-07-09
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    相关资源
    最近更新 更多