首页 > 解决方案 > 在多个 json 结构中按键搜索多个元素

问题描述

我需要获取与items键匹配的所有数组的值。我正在用Javascript编写一个脚本,该脚本需要读取多个jsonitems文件中多个数组中的对象,但每个 json 都有不同的结构。例子:

文件 1.json:

{
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}

文件2.json

{
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}

期望的结果:

{
   "data":[
      {
         "items":[
            {
               "name":"item1"
            }
         ]
      },
      {
         "items":[
            {
               "name":"randomItem2"
            }
         ]
      },
      {
         "items":[
            {
               "name":"item87"
            }
         ]
      },
      {
         "items":[
            {
               "name":"randomItem35"
            }
         ]
      }
   ]
}

在这两个文件中,我想提取具有 key 的数组items。在上面的示例中,脚本应该找到 4 个数组。正如您在两个文件中看到的那样,每个数组的嵌套方式都不同。我怎样才能使用 Javascript 做到这一点?

标签: javascriptnode.jsjson

解决方案


这将做到:

function omit(key, obj) {
  const { [key]: omitted, ...rest } = obj;
  return rest;
}

function getItems(obj) {
  return (typeof obj === 'object'
    ? 'items' in obj
      ? [{ items: obj.items }].concat(getItems(omit('items', obj)))
      : Object.values(obj).map(v => getItems(v))
    : []
  ).flat()
}
console.log({
  data: [file1, file2].map(o => getItems(o)).flat()
})

看到它工作:

const file1 = {
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}
const file2 = {
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}

function omit(key, obj) {
  const { [key]: omitted, ...rest } = obj;
  return rest;
}

function getItems(obj) {
  return (typeof obj === 'object'
    ? 'items' in obj
      ? [{ items: obj.items }].concat(getItems(omit('items', obj)))
      : Object.values(obj).map(v => getItems(v))
    : []
  ).flat()
}
console.log({
  data: [file1, file2].map(o => getItems(o)).flat()
})

让我们更进一步,使其具有通用性(使用对象数组并提取任何键)并将其作为函数提供,您也可以在其他项目中使用它:

function extractKey(objects, key) {
  const omit = (key, obj) => {
    const { [key]: omitted, ...rest } = obj;
    return rest;
  }

  const getValues = (obj) => (typeof obj === 'object'
    ? key in obj
      ? [{ [key]: obj[key] }].concat(getValues(omit(key, obj)))
      : Object.values(obj).map(o => getValues(o))
    : []
  ).flat();
  
  return objects.map(o => getValues(o)).flat()
}

// use: 
extractKey([file1, file2], 'items');

看到它工作:

function extractKey(objects, key) {
  const omit = (key, obj) => {
    const { [key]: omitted, ...rest } = obj;
    return rest;
  }

  const getValues = (obj) => (typeof obj === 'object'
    ? key in obj
      ? [{ [key]: obj[key] }].concat(getValues(omit(key, obj)))
      : Object.values(obj).map(o => getValues(o))
    : []
  ).flat();
  
  return objects.map(o => getValues(o)).flat()
}

// test:

const file1 = {
   "name":"First file",
   "randomName3874":{
      "items":[
         {
            "name":"item1"
         }
      ]
   },
   "items":[
      {
         "name":"randomItem2"
      }
   ]
}
const file2 = {
   "name":"Another file",
   "randomName00000":{
      "nestedItems":{
         "items":[
            {
               "name":"item87"
            }
         ]
      }
   },
   "stuff":{
      "items":[
         {
            "name":"randomItem35"
         }
      ]
   }
}


console.log(
  { data: extractKey([file1, file2], 'items') }
)


推荐阅读