Как объединить несколько файлов Json в папке в определенном порядке - PullRequest
1 голос
/ 07 июня 2019

У меня есть несколько файлов JSON в папке, и я хочу объединить их в один, следуя определенному порядку, указанному в order.json

Я протестировал приведенный ниже код, который объединяет все файлы, но в алфавитном порядке на основе имени файла.

jq -s . *.json > Merged.json

Это файл Shoes.json

{ "document": { "product": "Shoes", "info": [ { "day": "1", "month": "1", "entry": "Some text about Shoes for day 1 and month 1", "code": "AJKD" }, { "day": "2", "month": "1", "entry": "Some text about Shoes for day 2 and month 1", "code": "KKGIR" } ] } }

Это файл Watches.json

{ "document": { "product": "Watches",   "info": [ { "day": "2", "month": "3",   "entry": "Some text about Watches for day 2 and month 3",   "code": "PEWQ" }    ] }     }

Это файл Accesories.json

{ "document": { "product": "Accesories",    "info": [ { "day": "7", "month": "2",   "entry": "Some text about Accesories for day 7 and month 2",    "code": "UYAAC" }   ] }     }

Это файл, который дает порядок, который я хочу получить в выводе order.json

{  
   "order":{  
      "product 1":"Watches",
      "product 2":"Accesories",
      "product 3":"Shoes"
   }
}

И файл вывода, который я хотел бы получить, был бы таким: Merged.json :

{  
   "document":[  
      {  
         "product":"Watches",
         "info":[  
            {  
               "day":"2",
               "month":"3",
               "entry":"Some text about Watches for day 2 and month 3",
               "code":"PEWQ"
            }
         ]
      },
      {  
         "product":"Accesories",
         "info":[  
            {  
               "day":"7",
               "month":"2",
               "entry":"Some text about Accesories for day 7 and month 2",
               "code":"UYAAC"
            }
         ]
      },
      {  
         "product":"Shoes",
         "info":[  
            {  
               "day":"1",
               "month":"1",
               "entry":"Some text about Shoes for day 1 and month 1",
               "code":"AJKD"
            },
            {  
               "day":"2",
               "month":"1",
               "entry":"Some text about Shoes for day 2 and month 1",
               "code":"KKGIR"
            }
         ]
      }
   ]
}

Может быть, кто-то может помочь мне с этим делом.

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Вот решение, которое использует order.json, чтобы определить, какие файлы должны быть прочитаны jq:

jq -n '{documents: [inputs.document]}' $(jq -r '.order[] + ".json"' order.json)

Подход, приведенный в качестве примера выше, имеет много преимуществ, но в приведенной выше строке приводятся различные предположения, которые могут быть необоснованными. Например, предполагается, что в именах файлов нет пробелов.

Надежная обработка имен файлов

Следующее предполагает функциональность bash-ful:

mapfile -t args < <(jq -r '.order[] + ".json"' order.json)
jq -n '{documents: [inputs.document]}' "${args[@]}"

Если ваш bash не имеет mapfile, вы можете установить переменную bash следующим образом:

args=()
while read -r f; do 
  args+=("$f")
done < <(jq -r '.order[] + ".json"' order.json)
1 голос
/ 08 июня 2019

Преимущество следующего решения состоит в том, что он не требует каких-либо специфических для оболочки функций и требует только одного вызова jq. Предполагается, что вы хотите иметь возможность обрабатывать произвольное количество файлов, как определено order.json. Среди других предположений можно сказать, что в pwd мы можем использовать шаблон [A-Z]*.json для выбора соответствующих «документов».

jq -n --argfile order order.json '
  INDEX(inputs.document;  .product) as $dict
  | reduce $order.order[] as $product ([]; . + [$dict[$product]])
  | {document: .}
' [A-Z]*.json

def INDEX

Если ваш jq не имеет INDEX/2, то, возможно, самое время обновить его; в качестве альтернативы, вы можете просто добавить (добавить) его def:

def INDEX(stream; idx_expr):
  reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
...