Как я могу заменить нулевое значение в документе json на определенное значение с помощью jq?

У меня есть файл json, который содержит nulls в качестве значений для некоторых ключей, которые я хотел бы заменить определенным значением.

Учитывая этот ввод:

{
  "id": null,
  "rows": [
    {
      "panels": [
        {
          "title": "Panel1",
          "datasource": null
        },
        {
          "title": "Panel2",
          "datasource": null
        }
      ]
    }
  ]
}

Я бы хотел

{
  "id": null,
  "rows": [
    {
      "panels": [
        {
          "title": "Panel1",
          "datasource": "mydb"
        },
        {
          "title": "Panel2",
          "datasource": "mydb"
        }
        ]
     }
  ]
}

В настоящее время я использую

sed 's/"datasource": null/"datasource": "mydb"/'

Это дает нужный мне результат, но я продолжаю думать, что стыдно использовать sed для этой работы, когда есть такие инструменты, как jq, которые могут работать с JSON гораздо лучше.


person holgero    schedule 14.10.2015    source источник


Ответы (3)


Сначала вам нужно определить объекты, которые вы хотите обновить. Поскольку вы хотите установить для нулевых источников данных панелей значение "mydb", вы можете сделать это:

$ jq '.rows[].panels[].datasource //= "mydb"' input.json

Если вы хотите обновить любое свойство datasource любого объекта на любом уровне, вы можете использовать .. для их рекурсивного поиска.

$ jq '(.. | select(objects | has("datasource"))).datasource //= "mydb"' input.json
person Jeff Mercado    schedule 14.10.2015
comment
Возможно ли это сделать только тогда, когда исправлен полный путь к полю источника данных? - person holgero; 14.10.2015
comment
Есть способы заставить его обновлять любое свойство datasource любого объекта на любом уровне. Я добавлю этот пример. - person Jeff Mercado; 14.10.2015
comment
@JeffMercado отличный ответ, что, если datasource не null? как мы можем проверить, если key ==null, то replace с "" - person Dakait; 14.06.2019
comment
@dakait в этом случае вы можете использовать альтернативный оператор (//). Это даст LHS, если не null/false, иначе RHS. - person Jeff Mercado; 14.06.2019
comment
@JeffMercado благодарен :) - person Dakait; 14.06.2019

Для справки, также довольно легко изменить все значения ключа, которые являются нулевыми (независимо от того, где они встречаются) на какое-либо другое значение. Версии jq > 1.5 включают определяемый jq фильтр walk/1, который можно использовать (например, путем копирования и вставки) и в других версиях jq.

Например, чтобы изменить все значения ключа, которые равны нулю, на 0, используя walk/1:

walk(if type == "object" then with_entries(.value //= 0) else . end)

Вот определение walk/1, предоставленное jq:

def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
    elif type == "array" then map( walk(f) ) | f
    else f
    end;
person peak    schedule 23.10.2015

Вот решение, которое использует tostream, reduce и setpath для установки любого атрибута листа datasource, значение которого равно null на "mydb".

reduce (tostream|select(length==2)) as [$p,$v] (
  .
; if $p[-1] == "datasource" and $v == null then setpath($p; "mydb") else . end
)
person jq170727    schedule 25.08.2017