修改复杂的深度嵌套 javascript 对象

Modify a complex deeply nested javascript object

假设您有一个复杂的深层嵌套对象,有 15 - 20 层,您想要根据字段查询其中的某个节点并修改特定属性。我们怎样才能实现它?

以下示例是人为设计的,对象不像我的情况那么复杂,也没有我的情况那么深,所以请不要提出类似 obj[phoneNumbers][0].number = somethingNew

的建议

我在下面的示例中使用名为 jsonpath 的库来查询特定节点并使用 jsonpath 表达式获取其值。

var jp = require("jsonpath");

const obj = {
  firstName: "John",
  lastName: "doe",
  age: 26,
  address: {
    streetAddress: "naist street",
    city: "Nara",
    postalCode: "630-0192"
  },
  phoneNumbers: [
    {
      type: "iPhone",
      number: "0123-4567-8888"
    },
    {
      type: "home",
      number: "0123-4567-8910"
    }
  ]
};

const number = jp.query(obj, "$.phoneNumbers[0].number");
console.log(number);

// outputs: [ '0123-4567-8888' ]

谢谢。

如果您可以使用 lodash (npm i --save lodash) (https://lodash.com/),那么获取或设置深度嵌套的值就很容易了。

获取深度嵌套的值:(https://lodash.com/docs#get)

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3

_.get(object, ['a', '0', 'b', 'c']);
// => 3

_.get(object, 'a.b.c', 'default');
// => 'default'

设置深度嵌套值:(https://lodash.com/docs#set)

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5

这是使用 object-scan 的答案。与 lodash 相比的主要优势在于我们可以指定更通用的路径表达式并同时针对多个目标执行命令。增加的功能会增加复杂性,因此选择哪一个取决于您的要求。

// const objectScan = require('object-scan');

const object = { a: [{ b: { c: 3 } }] };

const get = (obj, needle) => objectScan([needle], {
  abort: true,
  rtn: 'value'
})(obj);

console.log(get(object, 'a[0].b.c'));
// => 3
console.log(get(object, '**.c'));
// => 3
console.log(get(object, 'a.b.c'));
// => undefined

const set = (obj, needle, val) => objectScan([needle], {
  filterFn: ({ parent, property }) => {
    parent[property] = val;
    return true;
  },
  abort: true,
  rtn: 'bool' // returns true iff executed
})(obj);

console.log(set(object, 'a[0].*.c', 4));
// => true
console.log(object);
// => { a: [ { b: { c: 4 } } ] }
console.log(set(object, 'x[0].y.z', 5));
// => false
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.7.1"></script>

免责声明:我是object-scan

的作者