首页 > 解决方案 > 如何使用点符号将 JSON 转换为键列表

问题描述

我正在使用点符号将 JSON 键转换为列表。如果有任何点表示嵌套的 jsonobject,并且如果有任何 [](array notation) 则表示 jsonarray。

var keyify = (obj, prefix = '') =>
  Object.keys(obj).reduce((res, el) => {
    if (Array.isArray(obj[el])) {
      return [...res, ...keyify(obj[el][0], prefix + el + '[].')];
    } else if (typeof obj[el] === 'object' && obj[el] !== null) {
      return [...res, ...keyify(obj[el], prefix + el + '.')];
    } else {
      return [...res, prefix + el];
    }
  }, []);

以上是我用于转换的示例代码。如果输入是

{
  "input": {
    "test": {
      "phone": [
        {
          "phone1": "123"
        }
      ]
    }
  },
  "customer": [
    {
      "lastname": "def",
      "firstname": "abc"
    }
  ]
}

输出将是:

[ 'input.test.phone[].phone1',
  'customer[].lastname',
  'customer[].firstname' ]

但是上面的代码只在 JSONArray 中搜索第一个 JSONObject 的键。但如果输入是这样的:

{
  "input": {
    "test": {
      "phone": [
        {
          "phone1": "123"
        },
        {
          "a": "456"
        }
      ]
    }
  },
  "customer": [
    {
      "lastname": "def",
      "firstname": "abc"
    }
  ]
}

然后在上面的 JSON 案例中,代码将给出输出:

[ 'input.test.phone[].phone1',
  'customer[].lastname',
  'customer[].firstname' ]

因此,a缺少的键仅phone1出现在列表中。因此,如何获取是否存在多个 json 键,然后获取具有首次出现索引的键。预期产出

[ 'input.test.phone[0].phone1',
  'input.test.phone[1].a',
  'customer[0].lastname',
  'customer[0].firstname' ]

如果 JSONarray 是值,则应将其替换为空字符串。

对于输入:

const data = {
  "input": {
    "test": {
      "phone": [
        {
          "phone1": ["123456"]
        },
        {
          "a": ["1","2","3","4"]
        }
      ]
    }
  },
  "customer": [
    {
      "lastname": "def",
      "firstname": "abc"
    }
  ]
}

在这种情况下"phone1": ["123456"],并且"a": ["1","2","3","4"]是 Json 数组作为值,这种情况下 lis 将类似于:预期输出:

[ 'input.test.phone[0].phone1',//instead of 'input.test.phone[0].phone1[0]'
  'input.test.phone[1].a',//instead of 'input.test.phone[1].a[0]','input.test.phone[1].a[1]','input.test.phone[1].a[2]','input.test.phone[1].a[3]',
  'customer[0].lastname',
  'customer[0].firstname' ]

在上述情况下,jsonarray 应该被视为值而不是键。

标签: javascript

解决方案


您可以使用for...in循环为此创建递归函数并检查当前数据输入是否为数组或不添加点或方括号。

const data =  { "input": { "test": { "phone": [ { "phone1": ["123456"] }, { "a": ["1","2","3","4"] } ] } }, "customer": [ { "lastname": "def", "firstname": "abc" } ] }

function parse(data, prev = '') {
  const result = []

  const check = data => {
    if (typeof data !== 'object') {
      return false
    }

    if (Array.isArray(data)) {
      if (data.some(e => (typeof e != 'object'))) {
        return false
      }
    }

    return true;
  }

  for (let i in data) {
    let dot = prev ? '.' : ''
    let str = Array.isArray(data) ? `[${i}]` : dot + i
    let key = prev + str;


    if (check(data[i])) {
      result.push(...parse(data[i], key))
    } else {
      result.push(key)
    }
  }

  return result
}

const result = parse(data);
console.log(result)


推荐阅读