Есть ли специальное значение для пропуска полей из вывода jq? - PullRequest
2 голосов
/ 08 марта 2020

Я могу легко условно установить поле в null:

echo '{"id": 1, "more": "fields"}' \
  | jq '{newId: (if .id == 1 then null else .id end), newMore: .more}'

приводит к

{
  "newId": null,
  "newMore": "fields"
}

Но как я могу условно удалить его? Я ищу что-то вроде:

echo '{"id": 1, "more": "fields"}' \
  | jq '{
          newId: (if .id == 1 then <special-value> else .id end), 
          newMore: .more
       }'

, чтобы получить

{
  "newMore": "fields"
}

Существует ли такой <special-value>? Если нет, каковы другие жизнеспособные решения? В идеале они также должны использоваться для больших объектов со многими дополнительными и вложенными полями.

Ответы [ 5 ]

1 голос
/ 09 марта 2020

Вы можете использовать empty в качестве специального значения вместе с // {}:

$ echo '{"id": 1}' | jq '{newId: (if .id == 1 then empty else .id end) } // {} '
{}

Этот метод также можно использовать для добавления поля условно, например,

$ echo '{"id": 1}' | jq '. += ({newId: (if .id == 1 then empty else .id end) } // {})'
{
  "id": 1
}

1 голос
/ 08 марта 2020

Используя jq 1.5 или более позднюю версию, вы можете использовать empty в качестве «специального значения» следующим образом:

echo '{"id": 1}' | jq '. as $in 
  | reduce "newId" as $k (.; .[$k] = if .id == 1 then empty else .id end)'

Дело в том, что таким способом вы можете обрабатывать неограниченное количество ключей; например, если у вас есть список имен ключей $ l, добавляемых условно, вы должны написать: reduce $l[] as $k ...

1 голос
/ 08 марта 2020

Вы можете принять соглашение, что, если значение ключа равно null (или nan), ключ может быть удален. Чтобы удалить все ключи с нулевым значением, вы можете использовать map_values(select(. != null)) (или map_values(select(isnan|not))).

Таким образом, используя ваш пример, мы находим:

$ echo '{"id": 1}' | jq '{newId: (if .id == 1 then null else .id end)} | map_values( select(. != null))'
{}

и:

$ echo '{"id": 1}' | jq '{newId: (if .id == 1 then nan else .id end)} | map_values( select(isnan|not))'
{}
1 голос
/ 08 марта 2020

В этом случае вы можете создать свой объект внутри оператора if:

echo '{"id": 1}' | jq 'if .id == 1 then {} else {newId: .id} end'
0 голосов
/ 08 марта 2020

Я теперь пошел с решением, где я условно добавляю поля в конце. Выглядит немного излишним для такого маленького объекта, но если вы имеете дело с большими объектами с большим количеством дополнительных полей, это очень чистый способ.

echo '{"id": 1, "more": "fields"}' \
| jq '.id as $id
       | {newMore: .more} 
       | if $id == 1 then . else . + {newId: $id} end
     '
...