web-dev-qa-db-fra.com

Fusionner les tableaux de JSON

Mon objectif est donc de fusionner les fichiers json pour obtenir ce format:

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    },
    {
      "name": "Al"
    }
  ]
}

Et j'ai des fichiers qui ressemblent à ce format:

blahblah.json

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    }
  ]
}

blueblue.json

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Al"
    }
  ]
}

Je peux stocker le tableau de liste de tous mes noms dans une variable avec les éléments suivants:

x = jq -s '.[].list' *.json

Et puis je prévoyais d'ajouter la variable à un tableau vide dans un fichier que j'ai créé, out.json, qui ressemble à ceci:

{
  "type": "NamesBook",
  "list": []
}

Cependant, lorsque mon script s'exécute sur la ligne

jq '.list[] += "$x"' out.json'

Cela fait apparaître une erreur jq:

Impossible d'itérer sur null.

Même lorsque j'ajoute un élément aléatoire, la même erreur apparaît. Conseils sur la façon de procéder? Existe-t-il d'autres outils dans jq pour faciliter la fusion des tableaux?

11
Waffy

Vous pouvez fusionner vos fichiers avec add (jq 1.3+):

jq -s '.[0].list=[.[].list|add]|.[0]' *.json

ou aplatir (jq 1.5+):

jq -s '.[0].list=([.[].list]|flatten)|.[0]' *.json

[.[].list] - crée un tableau de tous les tableaux "liste"

 [
  [
    {
      "name": "Ajay"
    }
  ],
  [
    {
      "name": "Al"
    }
  ]
]

[.[].list]|flatten - aplatir it (ou .[].list|add - ajouter tous les tableaux ensemble)

[
  {
    "name": "Ajay"
  },
  {
    "name": "Al"
  }
]

.[0].list=([.[].list]|flatten)|.[0] - remplacez la première "liste" par celle fusionnée, affichez-la.

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    },
    {
      "name": "Al"
    }
  ]
}
10
zeppelin

En supposant que chaque fichier aura le même title et que vous combinez simplement le contenu list, vous pouvez faire ceci:

$ jq 'reduce inputs as $i (.; .list += $i.list)' blahblah.json blueblue.json

Cela prend simplement le premier élément et ajoute à sa liste, la liste de toutes les autres entrées.

8
Jeff Mercado

L'OP n'a pas précisé ce qui devrait se produire s'il y a des objets pour lesquels .title n'est pas "NamesBook". Si l'intention est de sélectionner des objets avec .title égal à "NamesBook", on pourrait écrire:

map(select(.title == "NamesBook"))
| {title: .[0].title, list: map( .list ) | add}

Cela suppose que jq est invoqué avec l'option -s.

Par ailleurs, add est le chemin à parcourir ici: simple et rapide.

2
peak