JQ, разделить огромный JSON массива и сохранить в файл с именем со значением - PullRequest
1 голос
/ 16 мая 2019

У меня есть JSON, содержащий массив объектов, каждый объект содержит уникальное значение в:

"id":"value"

Я следовал этому Другой ответ , и я могу разделить весь документв нескольких файлах, используя jq и awk

jq -c ".[]" big.json | gawk '{print > "doc00" NR ".json";}'

, таким образом, выходные файлы именуются последовательно.
как я могу назвать файлы, используя значение id?

Ответы [ 3 ]

1 голос
/ 16 мая 2019

Использование .id в качестве части имени файла сопряжено с риском.

Во-первых, существует потенциальная проблема встроенных символов новой строки.

Во-вторых, существует проблема «зарезервировано»."символы, в частности" /".

В-третьих, Windows имеет многочисленные ограничения на имена файлов - см., например, https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3).

Кроме того, если используется опция -r jq, как предложено в другомпосле публикации на этой странице значения .id "1" и 1 будут сопоставлены с 1, что приведет к потере данных, если в awk используется «>».

Так что здесьпредставляет собой решение, иллюстрирующее, как можно достичь безопасности в среде OS X или * ix, и которое имеет большое значение для безопасного решения для Windows:

jq -c '.[]
       | (.id | if type == "number" then .
                else tostring | gsub("[^A-Za-z0-9-_]";"+") end), .' |
awk '
  function fn(s) { sub(/^\"/,"",s); sub(/\"$/,"",s); return s ".json"; }
  NR%2{f=fn($0); next} 
  {print >> f; close(f);}
' 

Обратите особое внимание на использование «>>» дляизбегать потери данных в случае конфликтов имен файлов.

1 голос
/ 16 мая 2019

Для каждого элемента в массиве выведите идентификатор и сам элемент в двух отдельных строках, поэтому вы можете извлечь идентификатор из нечетных строк и распечатать четные строки в файлы с именами с идентификатором.

jq -cr '.[] | .id, .' big.json | awk 'NR%2{f=$0".json";next} {print >f;close(f)}'
0 голосов
/ 17 мая 2019

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

Вкратце, вместо обычного вызова jq, добавляются параметры командной строки -n и --stream и заменяется исходный .[] на:

fromstream(1|truncate_stream(inputs))

Затем можно выполнить обработку разбиения, как описано в другом месте на этой странице.

...