JQ仅在存在时才创建字段

时间:2017-01-24 08:37:17

标签: json filter key jq

在jq中,如何确保k,v仅在被检查对象中存在时创建?例如,让我们说我有一个像这样的对象:

{
 "student":{
    "name": "george",
    "age" : "15",
    "quote": "Hello I am George"
    }
 }

cat text.txt | jq '{name: .student.name, quote: .student.quote}' 创建:

  {
   "name": "george",
   "quote": "Hello I am George"
   }

然而,有些条目不完整,我不想写一个空的K,V。我们说我得到了:

{
 "student":{
    "name": "Shirley"
  }
} 

使用上面的当前jq,这将创建:

 {
  "name": "Shirley",
  "quote": " ",
  }

有没有办法告诉jq只创建'quote'密钥(如果它不存在)?或者更一般地,只有在被检查对象中存在所有密钥时才创建所有密钥。

2 个答案:

答案 0 :(得分:1)

这是对象添加非常方便的地方,特别是因为$obj + null产生$obj(如果$obj是JSON对象):

.student |  {name} + if has("quote") then {quote} else null end

或等效地:

def maybe(k): if has(k) then {(k): .[k]} else null end;
.student |  {name} + maybe("quote")

稍微不同的方法,具有微妙的不同语义,将是:

.student |  {name} + ((select(.quote) | {quote}) // null)

当然其他变化也是可能的。

答案 1 :(得分:1)

如果您提前知道密钥是什么并且它们是直接属性,只需构建所需的密钥数组并检查对象是否包含这些密钥。

$ jq --argjson keys '["name","quote"]' '
def copy_keys($keys): . as $o
    | reduce $keys[] as $k ({}; if ($o|has($k)) then .[$k] = $o[$k] else . end)
    ;
.student | copy_keys($keys)' text.txt

但是你提出问题的方式,“或者更一般地说,只有当它们存在于被检查的对象中时才创建所有字段,”你只需要对象中的所有键,只要它有一把钥匙。为什么不直接拿到对象?

$ jq '.student' text.txt