web-dev-qa-db-fra.com

Comment fusionner 2 fichiers JSON en utilisant jq?

J'utilise les outils jq (jq-json-processeur) du script shell pour analyser json.

J'ai 2 fichiers json et veux les fusionner en un fichier unique

Voici le contenu des fichiers:

fichier1

{
    "value1": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2"
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        }
    }
}

fichier2

{
    "status": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value3": "v3"
        },      
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

résultat attendu

{
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        },
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

J'essaie beaucoup de combinaisons mais le seul résultat obtenu est le suivant, qui n'est pas le résultat attendu:

{
  "ccc": {
    "value2": "v2",
    "value1": "v1"
  },
  "bbb": {
    "value2": "v2",
    "value1": "v1"
  },
  "aaa": {
    "value2": "v2",
    "value1": "v1"
  }
}
{
  "ddd": {
    "value4": 4,
    "value3": "v3"
  },
  "bbb": {
    "value3": "v3"
  },
  "aaa": {
    "value4": 4,
    "value3": "v3"
  }
}

En utilisant cette commande:

jq -s '.[].value' file1 file2
97
Janfy

Depuis la version 1.4, cela est maintenant possible avec le * _ opérateur. Lorsque deux objets sont donnés, il les fusionnera de manière récursive. Par exemple,

jq -s '.[0] * .[1]' file1 file2

Vous obtiendriez:

{
  "value1": 200,
  "timestamp": 1382461861,
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  },
  "status": 200
}

Si vous souhaitez également vous débarrasser des autres clés (comme le résultat attendu), vous pouvez le faire comme suit:

jq -s '.[0] * .[1] | {value: .value}' file1 file2

Ou le supposé un peu plus efficace (car il ne fusionne aucune autre valeur):

jq -s '.[0].value * .[1].value | {value: .}' file1 file2
112
Simo Kinnunen

Utilisez jq -s add:

$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
  "a": 0,
  "b": "bar",
  "c": "baz"
}

Ceci lit tous les textes JSON de stdin dans un tableau (jq -s Le fait) puis les "réduit".

(add est défini comme def add: reduce .[] as $x (null; . + $x);, qui parcourt les valeurs/object du tableau en entrée et les ajoute. Ajout d'objet == fusion.)

47
user2259432

Qui sait si vous en avez encore besoin, mais voici la solution.

Une fois arrivé au --Slurp option, c'est facile!

--Slurp/-s:
    Instead of running the filter for each JSON object in the input,
    read the entire input stream into a large array and run the filter just once.

Puis le + l'opérateur va faire ce que vous voulez:

jq -s '.[0] + .[1]' config.json config-user.json

(Remarque: si vous souhaitez fusionner des objets internes au lieu de simplement écraser ceux de fichier gauche avec ceux de fichier de droite, vous devrez le faire manuellement.)

29
FiloSottile

Voici une version qui fonctionne de manière récursive (en utilisant *) sur un nombre arbitraire d'objets:

echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --Slurp 'reduce .[] as $item ({}; . * $item)'
{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}
15
jrib

Premièrement, {"valeur":. Valeur} peut être abrégé en {valeur}.

Deuxièmement, l'option --argfile (disponible dans jq 1.4 et jq 1.5) peut être intéressante car elle évite d'avoir à utiliser l'option --Slurp.

En regroupant ces éléments, les deux objets des deux fichiers peuvent être combinés de la manière spécifiée comme suit:

$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'

Le drapeau '-n' indique à jq de ne pas lire stdin, car les entrées proviennent des options --argfile ici.

5
peak