json 删除所有空值

1yjd4xko  于 2023-02-01  发布在  其他
关注(0)|答案(8)|浏览(219)

我正在尝试使用jq从json对象中删除null值。我在它们的github上找到了this issue,所以现在我正在尝试使用del删除它们。

'{ id: $customerId, name, phones: ([{ original: .phone }, 
 { original: .otherPhone}]), email} | del(. | nulls)'

这看起来没有任何作用,但是如果我用.phones替换nulls,它确实会删除电话号码。

qcbq4gxm

qcbq4gxm1#

下面演示了如何从JSON对象中删除所有空值键:

jq -n '{"a":1, "b": null, "c": null} | with_entries( select( .value != null ) )'
{
  "a": 1
}

或者,paths/0可按如下方式使用:

. as $o | [paths[] | {(.) : ($o[.])} ] | add

顺便说一下,del/1也可用于实现相同的结果,例如使用以下滤波器:

reduce keys[] as $k (.; if .[$k] == null then del(.[$k]) else . end)

或者不那么明显,但更简洁:

del( .[ (keys - [paths[]])[] ] )

为了记录在案,这里有两种使用delpaths/1的方法:

jq -n '{"a":1, "b": null, "c": null, "d":2} as $o
  | $o
  | delpaths( [  keys[] | select( $o[.] == null ) ] | map( [.]) )'

$ jq -n '{"a":1, "b": null, "c": null, "d":2}
  | [delpaths((keys - paths) | map([.])) ] | add'

在后两种情况下,输出是相同的:{" a ":1," d ":2)
作为参考,如果你想从JSON文本中的所有JSON对象中移除空值键(即递归地),你可以使用walk/1,或者:

del(.. | objects | (to_entries[] | select(.value==null) | .key) as $k | .[$k])
r7knjye2

r7knjye22#

This answer by Michael Homer on https://unix.stackexchange.com有一个超级简洁的解决方案,它从jq1.6:

del(..|nulls)

它会从JSON中删除所有空值属性(和值)。
nulls是一个内置过滤器,可由自定义选择替换:

del(..|select(. == "value to delete"))

要根据多个条件删除元素,例如删除所有布尔值和所有数字:

del(..|booleans,numbers)

或者,仅删除不符合条件的节点:

del(..|select(. == "value to keep" | not))

(The最后一个例子只是说明性的-当然你可以用==交换!=,但有时这是不可能的。例如,* 保留 * 所有真实值:del(..|select(.|not))

c3frrgcw

c3frrgcw3#

到目前为止,所有其他的答案都是针对旧版本jq的解决方案,在最新发布的版本中如何简单地做到这一点还不清楚。在JQ 1.6或更新版本中,这将完成递归删除null的工作:

$ jq 'walk( if type == "object" then with_entries(select(.value != null)) else . end)' input.json

来源于对上游讨论添加walk()函数的问题的评论。

cxfofazt

cxfofazt4#

[警告:本答复中给出的walk/1的定义是有问题的,尤其是第一条评论中给出的原因;还要注意,JQ1.6不同地定义了walk/1
我添加新的答案是为了强调@jeff-mercado脚本的扩展版本。我的脚本版本假设空值如下所示:

  • null;
  • []-空数组;
  • {}-空对象。

删除空数组和对象是从这里https://stackoverflow.com/a/26196653/3627676借用的。

def walk(f):
    . as $in | 
    if type == "object" then
        reduce keys[] as $key
            ( {}; . + { ($key): ( $in[$key] | walk(f) ) } ) | f
    elif type == "array" then 
        select(length > 0) | map( walk(f) ) | f
    else 
        f
    end;

walk(
    if type == "object" then
        with_entries(select( .value != null and .value != {} and .value != [] ))
    elif type == "array" then
        map(select( . != null and . != {} and .!= [] ))
    else
        .
    end
)
vs91vp4v

vs91vp4v5#

这不是del/1的本意,给定一个对象作为输入,如果你想删除.phones属性,你可以这样做:

del(.phones)

换句话说,del的参数是要删除的属性的路径。
如果你想使用这个函数,你必须找出null值的所有路径,并把它传递给this,这会很麻烦。
流输入可以使这项任务更加简单。

fromstream(tostream | select(length == 1 or .[1] != null))

否则,为了更简单的方法,你必须遍历对象树来找到null值,如果找到了,过滤掉它,使用walk/1,你的过滤器可以递归地应用来排除null值。

walk(
    (objects | with_entries(select(.value != null)))
    // (arrays | map(select(. != null)))
    // values
)

如果你有这个作为输入:

{
    "foo": null,
    "bar": "bar",
    "biz": [1,2,3,4,null],
    "baz": {
        "a": 1,
        "b": null,
        "c": ["a","b","c","null",32,null]
    }
}

该过滤器将产生:

{
    "bar": "bar",
    "baz": {
        "a": 1,
        "c": ["a","b","c","null",32]
    },
    "biz": [1,2,3,4]
}
polkgigr

polkgigr6#

在本页的其他地方,有人对使用jq来递归地消除[]和{}以及null的出现表示了兴趣。
虽然可以使用walk/1的内置定义来实现这一点,但要正确地实现这一点有点棘手,因此下面是walk/1的一个变体版本,它使实现这一点变得微不足道:

def traverse(f):
  if type == "object" then map_values(traverse(f)) | f
  elif type == "array" then map( traverse(f) ) | f
  else f
  end;

为了便于修改删除元素的标准,我们定义:

def isempty: .==null or ((type|(.=="array" or .=="object")) and length==0);

现在的解决方案很简单:

traverse(select(isempty|not))
vsmadaxz

vsmadaxz7#

使用较新版本的jq(1.6及更高版本)

可以使用此表达式递归地移除空值键:

jq 'walk( if type == "object" then with_entries(select(.value != null)) else . end)'

参考

iqjalb3h

iqjalb3h8#

[警告:下面的响应有几个问题,尤其是0|length为0这一事实引起的问题。]
详细说明前面的答案,除了删除具有null值的属性外,删除具有空数组或对象值(即[]{})的JSON属性通常也很有帮助。
-️jq的walk()函数(walk/1)使这一点变得简单。walk()将在jq的未来版本(〉jq-1.5)中提供,但它的定义可以添加到当前的过滤器中。
传递给walk()以删除null和空结构的条件是:

walk(
  if type == "object" then with_entries(select(.value|length > 0))
  elif type == "array" then map(select(length > 0))
  else .
  end
)

给定以下JSON输入:

{
  "notNullA": "notNullA",
  "nullA": null,
  "objectA": {
    "notNullB": "notNullB",
    "nullB": null,
    "objectB": {
      "notNullC": "notNullC",
      "nullC": null
    },
    "emptyObjectB": {},
    "arrayB": [
      "b"
    ],
    "emptyBrrayB": []
  },
  "emptyObjectA": {},
  "arrayA": [
    "a"
  ],
  "emptyArrayA": []
}

使用此函数可得到以下结果:

{
  "notNullA": "notNullA",
  "objectA": {
    "notNullB": "notNullB",
    "objectB": {
      "notNullC": "notNullC"
    },
    "arrayB": [
      "b"
    ]
  },
  "arrayA": [
    "a"
  ]
}

相关问题