javascript - 如何使用点符号将 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 应该被视为值而不是键。
解决方案
您可以使用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)
推荐阅读
- sql-server - 非聚集索引包含列导致高碎片
- c++ - 如何让 cpplint 检查 4 空格缩进而不是 2 空格缩进?
- matlab - 如何将误差线添加到 MatLab 的 cftool 生成的曲线拟合散点图?
- c++ - 在第一个参数上部分特化模板
- java - How to mock HttpClient class to return different responses
- haskell - 实现展平
- google-cloud-platform - Cloud DNS 上的尾随点
- azure - 保护 Azure Active Directory B2C 访问令牌和刷新令牌
- php - Magento 1.9 如果 SKU 代码等于...代码示例不起作用 - 帮助:D
- firebase - Firebase 实时数据库多位置更新通过云功能事务不起作用