【问题标题】:Remove parent JSON element depending on child value根据子值删除父 JSON 元素
【发布时间】:2020-05-29 01:06:46
【问题描述】:

我有一个包含大量空内容的 JSON:

{
    "items": [
        {
            "category": "login",
            "fields": [
                {
                    "label": "Name",
                    "value": "",
                },
                {
                    "label": "E-Mail",
                    "value": "",
                },
                {
                    "label": "Password",
                    "value": "123456",
                },
                {
                    "label": "Website",
                    "fields": [
                        {
                            "label": "Name X",
                            "value": ""
                        },
                        {
                            "label": "Name Y",
                            "value": "another one"
                        },…
                    ]
                },…
            ]
        },…
    ]
}

嵌套更深了几个层次。这仅显示第一级。我想删除“字段”的所有元素(或者更深层次的数组键),其中它们的“值”为空。

{
    "items": [
        {
            "category": "login",
            "fields": [
                {
                    "label": "Password",
                    "value": "123456",
                },
                {
                    "label": "Website",
                    "fields": [
                        {
                            "label": "Name Y",
                            "value": "another one"
                        },…
                    ]
                },…
            ]
        },…
    ]
}

如何在 Javascript 中做到这一点?

【问题讨论】:

  • 这不是一个微不足道的问题,因此您可能需要详细说明一下。您可能不得不求助于递归。因此,您想要的行为是:遍历具有 value 属性的 objects 的所有 arrays,并从array 如果value 为空?能否请您包含一个可用输入数据的摘录(最好是一个多个级别的)并显示您想要的输出是什么?
  • 相应地编辑了代码以反映“更深”。

标签: javascript json


【解决方案1】:

嗯,我找到了一种遍历 JSON 对象的方法:

function remove(jsondata) {
  for (let i in jsondata) {
    if (jsondata[i].value != undefined && jsondata[i].value == '') {
       delete jsondata[i];
    }
    else if (typeof jsondata[i] === "object") remove(jsondata[i]);
  }
}

不确定,如果它是最优雅的方式,但到目前为止它有效。

【讨论】:

  • +1。我个人认为它看起来干净而优雅。它必须有递归。如果可行,请务必选择您自己的答案作为选定的解决方案。
【解决方案2】:

使用filter方法,可以得到一个过滤后的数组
它返回Boolean。如果value存在,那就是真的

var list=JSON.parse(data)
list.items=list.items.map(val=>{
  val.fields=val.fields.filter(v=>v.value})
  return val
})

【讨论】:

  • 虽然此代码可以解决 OP 的问题,但最好包含关于您的代码如何解决 OP 问题的说明。这样,未来的访问者可以从您的帖子中学习,并将其应用到他们自己的代码中。 SO 不是编码服务,而是知识资源。此外,高质量、完整的答案更有可能得到支持。这些功能,以及所有帖子都是独立的要求,是 SO 作为一个平台的一些优势,使其与论坛区分开来。您可以编辑以添加其他信息和/或使用源文档补充您的解释。
  • 我认为它根本不能解决 OP 的问题。 OP 特别指出嵌套更深几级,因此您可能希望使用递归来遍历那些n 级别。这个解决方案不会比第一级更深入——更不用说在遍历时必须确定一个元素是对象、数组还是原始值来决定如何处理它。不是一个简单的任务。公平地说,这是一个表述不当的问题(这正是它被否决的原因,而不是我的反对)。
  • @gyohza 你是对的,但作者没有给出deeper 代码
  • 你是对的。我问了cmets中的OP。让我们等着看。 :)
【解决方案3】:

我们将object-scan 用于许多数据处理任务。一旦你把头绕在它周围,它就会很强大。以下是您如何回答您的问题

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

const prune = (input) => objectScan(['**[*].value'], {
  rtn: 'count',
  filterFn: ({ gparent, gproperty, value }) => {
    if (value === '') {
      gparent.splice(gproperty, 1);
      return true;
    }
    return false;
  }
})(input);

const obj = { items: [{ category: 'login', fields: [{ label: 'Name', value: '' }, { label: 'E-Mail', value: '' }, { label: 'Password', value: '123456' }, { label: 'Website', fields: [{ label: 'Name X', value: '' }, { label: 'Name Y', value: 'another one' }] }] }] };

console.log(prune(obj)); // return count of pruned entries
// => 3
console.log(obj);
// => { items: [ { category: 'login', fields: [ { label: 'Password', value: '123456' }, { label: 'Website', fields: [ { label: 'Name Y', value: 'another one' } ] } ] } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@16.0.0"></script>

免责声明:我是object-scan的作者

【讨论】:

  • 非常有趣。谢谢你。
猜你喜欢
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
相关资源
最近更新 更多