删除所有空值

时间:2016-09-14 22:29:26

标签: json bash null jq

我正在尝试使用jq从json对象中删除空值。我在他们的github上找到this issue,所以现在我试图用del删除它们。 我有这个:

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

这似乎没有做任何事情。但是,如果我将nulls替换为.phones,则会删除电话号码。

8 个答案:

答案 0 :(得分:6)

以下说明如何从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     }

答案 1 :(得分:2)

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

del(.phones)

换句话说,del的参数是您要删除的属性的路径。

如果你想使用它,你必须找出null值的所有路径并将其传递给它。那会更麻烦。

为了更简单的方法,您必须遍历对象树以查找null值。如果找到,请删除相应的属性(或以其他方式将其过滤掉)。使用walk/1,您的过滤器可以递归应用,以排除null值。

walk(
    if type == "object" then
        with_entries(select(.value != null))
    elif type == "array" then
        map(select(. != null))
    else
        .
    end
)

所以,如果你有这个输入:

{
    "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]
}

walk/1将在未来版本的jq中添加,因此您必须添加它。您可以获取定义here

# Apply f to composite entities recursively, and to atoms
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys_unsorted[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;

答案 2 :(得分:2)

[警告:此回复中给出的walk/1的定义存在问题,尤其是出于第一条评论中给出的原因;另请注意,jq 1.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
)

答案 3 :(得分:1)

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

您可以使用此表达式递归删除空值键:

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

REF

答案 4 :(得分:0)

[警告:以下回复有几个问题,尤其是因$ans = preg_match_all("/\b$now $next\b/ui", $text_file); // here __^ 为0而引起的问题。]

earlier answer进行阐述,除了删除具有0|length值的属性外,删除具有空数组或对象值的JSON属性(即null或{{1}通常很有帮助也是。

  

ℹ️ - jq的[]函数({})使这很容易。 walk()将是。{   在jq(> walk/1)的未来版本中可用,但its definition   可以添加到当前过滤器。

传递给walk()以删除空值和空结构的条件是:

jq-1.5

鉴于此JSON输入:

walk()

使用此功能可得出结果:

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

答案 5 :(得分:0)

在此页面的其他地方,人们表达了一些兴趣 使用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))

答案 6 :(得分:0)

到目前为止,所有其他答案都是旧版本jq的变通办法,目前尚不清楚如何在最新发行的版本中做到这一点。在JQ 1.6或更高版本中,这将以递归方式删除null:

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

来自this comment,是在上游讨论添加walk()函数的问题。

答案 7 :(得分:0)

This answerMichael Homer

https://unix.stackexchange.com 有一个超级简洁的解决方案,从 jq 1.6 开始就可以使用:

del(..|nulls)

它会从您的 JSON 中删除所有空值属性(和值)。简单又甜蜜:)

nulls 是一个内置过滤器,可以用自定义选择替换:

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

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

del(..|booleans,numbers)

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

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

(最后一个例子只是说明性的——当然你可以将 == 换成 !=,但有时这是不可能的。例如,保留所有真值:{ {1}})