Использование JQ для преобразования обычного текстового блока в JSON

#json #jq #key-value

#json #jq #ключ-значение

Вопрос:

У меня есть обычный текстовый файл в формате, подобном этому:

 foo: bar
color: blue
names: joe, john, mary, bob, sue
 

Мне нужно вывести содержимое этого файла в формате JSON:

 {
  "foo": "bar",
  "color": "blue",
  "names": ["joe", "john", "mary", "bob", "sue"]
}
 

Я пытался использовать: jq -R -n '[inputs|split(":")|[{(.0):.[1] | add' testfile (допустим, имя файла — testfile), но я могу получить только этот результат:

 {
  "foo": "bar",
  "color": "blue",
  "names": "joe, john, mary, bob, sue"
}
 

Что мне нужно сделать, чтобы получить желаемый результат? Я пробовал конвейер split(",") после [1] , но он превращает каждую пару значений в массив, чего я не хочу.

Ответ №1:

Всегда разделяйте значение. Если результирующий массив содержит несколько элементов, назначьте его; в противном случае назначьте исходную строку.

 reduce (inputs / ": ") as [$k, $v] (.;
  .[$k] = ($v / ", " | if has(1) then . else $v end)
)
 

Онлайн-демонстрация

Или сначала проверьте, содержит ли значение разделитель, а затем разделите, если это имеет больше смысла.

           ($v | if index(", ") then split(", ") else . end)
 

Онлайн-демонстрация

Обратите внимание, что для этого необходимо вызвать JQ с помощью -R и -n в командной строке.

Ответ №2:

С --raw-input помощью, вы ищете что-то вроде этого:

   [., inputs]                                                              # A
| map(split(": ")                                                          # B
  | {(.[0]): (.[1] | split(", ") | if length > 1 then . else .[0] end )})  # C
| reduce .[] as $x ({}; .   $x)                                            # D

 

Где:

  • A: объединяет первую и последнюю строки в один массив, например ["foo: bar", …]
  • B: разделить каждую строку, например [["foo", "bar"], …]
  • C: Преобразуйте каждое подмножество в объект, где первый элемент является ключом, а второй элемент — значением. Значение разделяется на ", " , но если после разделения остается только один элемент, удалите его.
  • D: объединить каждый объект в один с помощью, например {"foo": "bar"} {"color": "blue"} , => {"foo": "bar", "color": "blue", …}