2016-02-25 5 views
3

Есть ли способ сделать хороший CSV из следующего кода JSON?Извлечение данных из необычного JSON

{ 
    "cod:[email protected]" : { 
     "typeA" : { 
      "lsk:d##fjd": { 
       "title" : "slkdfjlkdjfd", 
       "year" : "2014" 
      }, 
     "sdfdsfsd" : { 
      "title" : "slkdfjlkdjfddewfsdfd", 
      "year" : "2015" 
      } 
     }, 
     "[email protected]" : { 
      "sd$!!fs:$dfds" : { 
       "title" : "slkdfjsdfsdfdsfsd", 
       "year" : "2012" 
      } 
     } 
    } 
} 

Вот что я пытался в JQ:

jq -rc 'keys[] as $x 
    | .[]|keys[] as $y 
    | .[]|keys[] as $z 
    |.[] 
    |[$x,$y,$z,.year] | @csv' 

jq -rc 'keys_unsorted[] as $x 
    | .[]|keys_unsorted[] as $y 
    | .[]|keys_unsorted[] as $z 
    | .[]|[$x,$y,$z,.year] | @csv' 

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

Фиксация оригинального поколения JSON на данный момент не является вариантом, поэтому любая помощь будет оценена.

В идеале, я хотел бы получить:

"cod:[email protected]","typeA","lsk:d##fjd","slkdfjlkdjfd","2014" 
"cod:[email protected]","typeA","sdfdsfsd","slkdfjlkdjfddewfsdfd","2015" 
"cod:[email protected]","[email protected]","sd$!!fs:$dfds","slkdfjsdfsdfdsfsd","2012" 
+0

Не могли бы вы описать, что должно быть "хорошим" выход из вашего примера. – Kordi

+0

Спасибо, исправил вопрос! – econ

+0

JSON, кажется, немного необычен, но отлично. Ничего «плохо структурированного». – gnasher729

ответ

1

Небольшая модификация скрипта, который вы предоставляете в начальном посте, заставляет его работать. Вместо использования. [], Я индексирую по определенному ключу, который сохраняется как переменная от keys_unsorted. Я также добавил заголовок в CSV для удобства:

jq -r '["x", "y", "z", "title", "year"], 
    (keys_unsorted[] as $x 
    | .[$x] | keys_unsorted[] as $y 
    | .[$y] | keys_unsorted[] as $z 
    | .[$z] | [$x, $y, $z, .title, .year]) | @csv' 

Это действительно обеспечивает вывод, который вы ищете (с заголовком):

"x","y","z","title","year" 
"cod:[email protected]","typeA","lsk:d##fjd","slkdfjlkdjfd","2014" 
"cod:[email protected]","typeA","sdfdsfsd","slkdfjlkdjfddewfsdfd","2015" 
"cod:[email protected]","[email protected]","sd$!!fs:$dfds","slkdfjsdfsdfdsfsd","2012" 
+0

Теперь я вижу, почему я получал все эти перестановки! Спасибо, в основном я должен был повторно использовать переменные, а не запускать новую ветку '[]'. :) – econ

0

Вы можете использовать 'https://github.com/zemirco/json2csv' с опцией flatten. Это приведет к созданию столбцов, таких как cod:[email protected]:d##fjd.title.

cat input.json | json2csv -F >> output.csv 

EDIT: Это не то, что вы хотите.

+1

Спасибо за ссылку json2csv, результат не то, что я ищу, но программа может быть удобной в будущем. – econ

0

Вот JQ скрипт, который проходит через «элементы листа» во входном и делает столбец CSV из каждого ключа она проходит через:

jq -r 'leaf_paths as $path | $path + [getpath($path)] | @csv' 

Обратите внимание, что это не совсем то, что вы ищете :

"cod:[email protected]","typeA","lsk:d##fjd","title","slkdfjlkdjfd" 
"cod:[email protected]","typeA","lsk:d##fjd","year","2014" 
"cod:[email protected]","typeA","sdfdsfsd","title","slkdfjlkdjfddewfsdfd" 
"cod:[email protected]","typeA","sdfdsfsd","year","2015" 
"cod:[email protected]","[email protected]","sd$!!fs:$dfds","title","slkdfjsdfsdfdsfsd" 
"cod:[email protected]","[email protected]","sd$!!fs:$dfds","year","2012" 
+0

Как вы пишете, это немного отличается от того, что я хочу, но очень работоспособным. – econ

2

Ниже приводится общее решение регулярно структурированы вложенные объекты (условно говоря, их можно рассматривать как «объекты бабушки», как вложенные куклы); кроме того, ключи в объектах могут быть заказаны любым способом.

Ключевым понятием является «скалярные объекты» - объекты, все ключи которых имеют значения .

Шаблон для информации, которая должна быть извлечена из «скалярных объектов» обеспечивается в качестве параметра к «испускать» фильтра и используется , чтобы гарантировать, что соответствующий порядок поддерживается при производстве строки CSV.

def emit(template): 

    def is_scalar_object: 
    def is_scalar: type | ((. != "object") and (. != "array")); 
    . as $in | (type == "object") and all($in[] | is_scalar); 

    . as $in 
    | paths as $path 
    | select(getpath($path) | is_scalar_object) 
    | $path + [ template + ($in | getpath($path)) | .[]] 
    ; 


data | emit({title, year}) | @csv 

Использование:

jq -r emit.jq input.json 

Выход:

"cod:[email protected]","typeA","lsk:d##fjd","slkdfjlkdjfd","2014" 
"cod:[email protected]","typeA","sdfdsfsd","slkdfjlkdjfddewfsdfd","2015" 
"cod:[email protected]","[email protected]","sd$!!fs:$dfds","slkdfjsdfsdfdsfsd","2012" 
+0

Большое спасибо! :) Я уже принял ответ и стесняюсь его менять, но, конечно, ваш ответ более общий. Это будет удобно в будущем! – econ

Смежные вопросы