【问题标题】:How do I loop through a JSON object in MarkLogic to push all the keys in an array?如何遍历 MarkLogic 中的 JSON 对象以推送数组中的所有键?
【发布时间】:2019-08-26 06:53:08
【问题描述】:

我有一个多级 JSON,如下例所示。我想编写一个简单的代码来循环遍历它并获取其中的所有键以进行验证。

我尝试了Object.keys(),但这只给出了对象第一级的键。我如何循环它以获得整个结果?

{
"id": "0001",
"ppu": 0.55,
"batters": {
    "batter": [{
            "id": "1001",
            "type": "Regular"
        },
        {
            "id": "1004",
            "type": "Devil's Food"
        }
    ]
},
"topping": {
    "id": "5001",
    "type": "None",
    "moreData": {
        "id": "5003",
        "type1": "Chocolate",
        "type2": {
            "id": "5004",
            "type": "Maple"
        }
    }
  }
}

我通常只得到第一个键,即“id”、“ppu”、“batters”、topping”,但我想要所有的键,包括“batter”、“type”、“moreData”等。 注意:与下面的示例不同,我所有的密钥都是唯一的。

编辑 - 我正在尝试的代码:

function keyCheck(obj) {
    var a = Object.keys(obj);
    var arr=[];
    arr.push(a);
    for (var i = 0; i < a.length; i++) {
        var b = obj[a[i]];
        if (typeof (b) == 'object') {
            keyCheck(b);
        }   
    }    
    return arr[0];
}
keyCheck(obj);

【问题讨论】:

  • 我认为这是一个关于递归获取对象键的更一般的 JavaScript 问题。周围有几个答案,以及帮助解决这个问题的库。例如:stackoverflow.com/questions/15690706/…
  • 我很难找到一个不太大且简单的最终函数。
  • 请添加预期结果和到目前为止您尝试过的内容
  • 实际:[["id", "ppu", "batters", "toppings"]] 预期:[["id", "ppu", "batters", "toppings", " type", "moreData","type1", "type2"]]
  • @Mehul 检查我的更新答案

标签: javascript arrays json object marklogic


【解决方案1】:

你可以写一个递归方法如下,

let obj = {
	"id": "0001",
	"ppu": 0.55,
	"batters": {
		"batter": [{
			"id": "1001",
			"type": "Regular"
		},
		{
			"id": "1004",
			"type": "Devil's Food"
		}
		]
	},
	"topping": {
		"id": "5001",
		"type": "None",
		"moreData": {
			"id": "5003",
			"type1": "Chocolate",
			"type2": {
				"id": "5004",
				"type": "Maple"
			}
		}
	}
}

function getKeys(obj, arr = []) {
	Object.entries(obj).forEach(([key, value]) => {
		if(typeof value === 'object' && !Array.isArray(value)) {
			arr.push(key);
			getKeys(value, arr);
		} else {
			arr.push(key);
		}
	});
	return arr;
}

console.log(getKeys(obj));

对于旧浏览器

function getKeys(obj, arr = []) {
    Object.entries(obj).forEach(function(entry) {
        let key = entry[0];
        let value = entry[1]
        if(typeof value === 'object' && !Array.isArray(value)) {
            arr.push(key);
            getKeys(value, arr);
        } else {
            arr.push(key);
        }
    });
    return arr;
}

【讨论】:

  • 在 MarkLogic 中,它说 Object.entries 不是函数。
  • 你可以在你的代码中添加polyfill。
  • 我猜 OP 正在 IE 中运行它,其中也不支持解构和箭头功能。 @Mehul 您可以在其他浏览器中尝试
  • 如果是这样,我也会删除这些。
【解决方案2】:

您可以通过使用Object.keys() 制作recursive 函数来实现此目的

    const object = {
      id: '0001',
      ppu: 0.55,
      batters: {
        batter: [{
          id: '1001',
          type: 'Regular',
        },
        {
          id: '1004',
          type: "Devil's Food",
        },
        ],
      },
      topping: {
        id: '5001',
        type: 'None',
        moreData: {
          id: '5003',
          type1: 'Chocolate',
          type2: {
            id: '5004',
            type: 'Maple',
          },
        },
      },
    };
    
    
    function getKeyNames(obj, secondObj) {
      Object.keys(obj).forEach((r) => {
        const elem = obj[r];
        const refObj = secondObj;
        if (!Array.isArray(elem)) {
          refObj[r] = r;
        }
        if (typeof elem === 'object' && (!Array.isArray(elem))) {
          getKeyNames(elem, secondObj);
        }
      });
      return secondObj;
    }
    
    function getAllKeys(obj) {
      const secondObj = {};
      const keys = getKeyNames(obj, secondObj);
      return Object.keys(keys);
    }
    
    const result = getAllKeys(object);
    console.log(result);

【讨论】:

  • 为什么投反对票?该解决方案与OP的问题相匹配
  • 为什么要创建一个对象而不是数组来进行聚合?并在对象中保持键和值相同然后只返回键?当对象通过引用传递时创建一个新对象const refObj = secondObj; 的意义何在?还将新的键值添加到引用的对象refObj 但最终返回secondObj?
  • @AZ_ 因为当你使用array 时,复制是可能的,而在``object` 中的键是unique,在这种情况下我们只需要keys,你不能创建一个像 const obj = { 'key1', 'key2', 'key3' } 这样的对象,所以我使用相同的键值对创建 object。
  • 将对象用于唯一值不是一种方法,您可以使用Set。此外,如果对象中已存在键,则您将覆盖键的值。我还提到了其他问题。
  • @AZ_ 我创建了一个新对象const refObj = secondObj; 因为当您配置诸如ESLint 之类的装饰器时,如果您尝试在secondObj 中进行更改,它们会给您一个警告no-param-reassign(即函数的参数),这就是为什么我用新变量(refObj)复制一个对象。然后你在refObj 中所做的任何更改,它都会复制到主obj secondObj,所以这里我使用refObj 间接更改secondObj 并返回secondObj。
【解决方案3】:

您可以使用递归函数来获取所有键。下面的方法采用第二个参数unique,它允许您设置键是否应该在生成的键数组中重复。

const allKeys = (obj, unique = true) => {
  const res = Object.entries(obj).flatMap(([k, v]) => {
    if (typeof v === 'object') {
      if (Array.isArray(v)) return [k, v.flatMap(vv => allKeys(vv, unique))].flat();
      return [k, allKeys(v, unique)].flat();
    }
    return k;
  });
  return unique ? [...new Set(res)] : res;
};


console.log(allKeys(obj));
<script>
  const obj = {
    "id": "0001",
    "ppu": 0.55,
    "batters": {
      "batter": [{
          "id": "1001",
          "type": "Regular"
        },
        {
          "id": "1004",
          "type": "Devil's Food"
        }
      ]
    },
    "topping": {
      "id": "5001",
      "type": "None",
      "moreData": {
        "id": "5003",
        "type1": "Chocolate",
        "type2": {
          "id": "5004",
          "type": "Maple"
        }
      }
    }
  };
</script>

【讨论】:

    【解决方案4】:

    JSON.parse reviver parameter 可用于获取所有键值对:

    var keys = {}, json = '{"id":"0001","ppu":0.55,"batters":{"batter":[{"id":"1001","type":"Regular"},{"id":"1004","type":"Devil\'s Food"}]},"topping":{"id":"5001","type":"None","moreData":{"id":"5003","type1":"Chocolate","type2":{"id":"5004","type":"Maple"}}}}'
    
    JSON.parse(json, function(key, value) { if ( isNaN(key) ) keys[key] = value })
    
    console.log( Object.keys(keys) )

    【讨论】:

    • 您不能只返回密钥。它将需要所有 OP 的验证逻辑移动到 JSON.parse 内,当验证失败时这将无济于事,否则您将不得不在 parse 内抛出错误。此外,它需要先对对象进行字符串化。
    【解决方案5】:

    所以我通过使用这里每个人提供的输入找到了一个解决方案。由于某些政策,我无法发布自己的解决方案,但这就是我所做的: 获取第一级数据的 Object.keys()。检查它是否是另一个对象或数组并递归调用相同的函数。如果没有,则将其添加到数组中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 2021-01-09
      • 1970-01-01
      • 2018-09-23
      • 2016-11-18
      相关资源
      最近更新 更多