Использование jq для изменения объекта json и значения поля из переменной - PullRequest
0 голосов
/ 09 февраля 2019

Я хочу изменить следующий json, используя переменные, указанные в оболочке bash Linux, используя jq.

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"

Мой json:

{
 "plants": {
  "flowers.small": {
    "colour": "",
    "age": "",
    "vegetables": {
     "root": "",
     "height": ""
    }
  }
 }
}

Я хочу изменить json, используя переменные в jq:

{
 "plants": {
  "${var2}": {
    "colour": "${var1}",
    "age": "",
    "${var3}": {
     "root": "",
     "height": "${var4}"
    }
  }
 }
}

Я пытаюсь просто установить значение поляиз переменных:

Команда:

cat myjson.json|jq '.plants["flowers.small"].colour = "${var1}"' -c

Результат:

{"plants":{"flowers.small":{"colour":"${var1}","age":"","vegetables":{"root":"","height":""}}}}

Команда :

cat myjson.json|jq --arg v "$var1" '.plants.["flowers.small"].colour = [$v]' -c

Результат:

jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.plants.["flowers.small"].colour = $v
jq: 1 compile error

Моя версия jq: jq-1.5-1-a5b5cbe

Как я могу переименовать поле и установить значение дляключ от переменных?Это даже выполнимо, используя версию jq?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Я подозреваю, что это очень близко к тому, что вы хотите:

#!/bin/bash

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"

jq --arg var1 "$var1" \
   --arg var2 "$var2" \
   --arg var3 "$var3" \
   --arg var4 "$var4" '
   {"${var1}": $var1, "${var2}": $var2, "${var3}": $var3, "${var4}": $var4} as $dict
   | walk( if type == "string" and $dict[.] then  $dict[.] 
           elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
           else . end)' template.json

Этот общий подход в порядке, но вы можете проверить jq Cookbook для предложений об использовании jq в качестве движка шаблонов: https://github.com/stedolan/jq/wiki/Cookbook#using-jq-as-a-template-engine

Модернизированная версия

Если ваш jq поддерживает $ARGS, то вы можете использовать эту модернизированную версию выше:

jq --arg '${var1}' "$var1" \
   --arg '${var2}' "$var2" \
   --arg '${var3}' "$var3" \
   --arg '${var4}' "$var4" '
    $ARGS.named as $dict
    | walk( if type == "string" and $dict[.] then  $dict[.] 
            elif type=="object" then with_entries(if $dict[.key] then .key |= $dict[.] else . end)
            else . end)' template.json
0 голосов
/ 09 февраля 2019

Использование jq в качестве движка шаблонов

Если вам не нужно на самом деле , нужно input.json в качестве отдельного файла, проще всего определить весь шаблон целикомкак выражение jq:

var1="red"
var2="european.flowers"
var3="european_vegetables"
var4="20"
jq -n --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '
{
 "plants": {
  "\($var2)": {
    "colour": $var1,
    "age": "",
    "\($var3)": {
     "root": "",
     "height": $var4
    }
  }
 }
}'

выводится как вывод:

{
  "plants": {
    "european.flowers": {
      "colour": "red",
      "age": "",
      "european_vegetables": {
        "root": "",
        "height": "20"
      }
    }
  }
}

Альтернативно: переименование поддеревьев

Если вы действительно делаете хотите переименовать существующий ключ, рассмотрите подход, подобный приведенному ниже.Использование переменных jq для полей шаблона не обязательно, но это облегчает изменение вашего кода позже:

var1="red"; var2="european.flowers"; var3="european_vegetables"; var4="20"

jq --arg var1 "$var1" --arg var2 "$var2" --arg var3 "$var3" --arg var4 "$var4" '

  # set variables for the fields we expect to see in our input
  "flowers.small" as $plant_tmpl |
  "vegetables" as $cat_tmpl |

  # change things inside fields we will later rename *before* we rename those fields
  .plants[$plant_tmpl].colour = $var1 |
  .plants[$plant_tmpl][$cat_tmpl].height = $var4 |

  if $var3 == $cat_tmpl then . else
    # var3 is not "vegetables" (templated value), so we need to rename it
    .plants[$plant_tmpl][$var3] = .plants[$plant_tmpl][$cat_tmpl] |
    del(.plants[$plant_tmpl][$cat_tmpl])
  end |

  if $var2 == $plant_tmpl then . else
    .plants[$var2] = .plants[$plant_tmpl] |
    del(.plants[$plant_tmpl])
  end
' <<'EOF'
{
 "plants": {
  "flowers.small": {
    "colour": "",
    "age": "",
    "vegetables": {
     "root": "",
     "height": ""
    }
  }
 }
}
EOF
...