Jq kullanarak 2 dosyadan 2 JSON nesnesi nasıl birleştirilir?


124

Jq kullanıyorum ayrıştırma json için kabuk komut dosyası araçları (jq-json işlemcili).

2 json dosyam var ve bunları tek bir dosyada birleştirmek istiyorum

İşte dosyaların içeriği:

dosya1

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

dosya2

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

Beklenen Sonuç

{
    "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
        }
    }
}

Çok fazla kombinasyon deniyorum ama aldığım tek sonuç şudur ki bu beklenen sonuç değildir:

{
  "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"
  }
}

Bu komutu kullanarak:

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

1
Jsontool denedin mi? github.com/trentm/json
— Nano Taboada

Henüz değil, bir göz atacağım. Thx
— Janfy

Bunu kullanarak yapmak jsoniçin:cat f1 f2 | json --deep-merge
— xer0x

json@ xer0x'i nereden / nasıl alırsınız ?
— Gus

@Gus oh, jsonaracı almak için github.com/trentm/json
— xer0x

Yanıtlar:


155

1.4'ten beri bu artık *operatörle mümkündür . İki nesne verildiğinde, onları yinelemeli olarak birleştirir. Örneğin,

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

Önemli: -s (--slurp)Dosyaları aynı diziye yerleştiren bayrağa dikkat edin.

Seni alır mıydı:

{
  "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
}

Diğer anahtarlardan da kurtulmak istiyorsanız (beklenen sonucunuz gibi), bunu yapmanın bir yolu şudur:

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

Ya da muhtemelen biraz daha etkilidir (çünkü diğer değerleri birleştirmez):

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

2
NOT : -sbayrak önemlidir, çünkü onsuz iki nesne bir dizide değildir.
— John Morales

1
@SimoKinnunen Burada iki json dosyasını birleştiriyoruz. 1 json değişkeni ve başka bir json dosyasına sahip olmak mümkün mü? Denedim ama benim için çalışmıyor gibi görünüyor!
— Jayesh Dhandha

Tek tek dosyalar bir anahtara göre sıralanırsa, ortaya çıkan dosyadaki sırayı korumak mümkün müdür?
— Leo

@SimoKinnunen Bu komutu kullanıyorum: "jq -s 'add' config.json diğer / *. Json" ama bir "cat config.json" yaptığımda birleştirilmiyor. Çıktıyı dosyaya nasıl geri koyabilirim?
— Renato Bibiano

63

Kullanım jq -s add:

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

Bu, tüm JSON metinlerini stdin'den bir diziye okur (jq -s bunu yapar) ve sonra onları "azaltır".

( addOlarak tanımlanır def add: reduce .[] as $x (null; . + $x);giriş dizinin / nesnenin değerleri üzerinden dolaşır ve. Nesne ek == birleştirme ekler ki,.)


4
Bu yaklaşımla yinelemeli birleştirme (* operatörü) yapmak mümkün mü?
— Dave Foster

1
@DaveFoster Evet, benzer bir şeyle reduce .[] as $x ({}; . * $x)- jrib'in cevabına da bakın .
— Chriki

Bu, Ansible ve jq kullanarak iki json dosyasını birleştirmeme yardımcı oldu. Teşekkürler.
— Felipe Alvarez

35

Hala ihtiyacınız olup olmadığını kim bilebilir, ama işte çözüm.

Bir kez --slurp geldiğinizde, çok kolay!

--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.

Sonra + operatör istediğinizi yapacak:

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

(Not: Soldaki dosya olanların üzerine doğru dosya olanların üzerine yazmak yerine iç nesneleri birleştirmek istiyorsanız, bunu manuel olarak yapmanız gerekecektir)


19

Burada *, rastgele sayıda nesne üzerinde özyinelemeli (kullanarak ) çalışan bir sürüm bulunmaktadır :

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

2
Mükemmel cevap. Bir dizindeki tüm dosyaları birleştirirken iyi çalışıyor:jq -s 'reduce .[] as $item ({}; . * $item)' *.json
— John Ellmore

7

İlk olarak, {"değer": .value} yalnızca {değer} olarak kısaltılabilir.

İkinci olarak, --argfile seçeneği (jq 1.4 ve jq 1.5'te mevcuttur), --slurp seçeneğini kullanmak zorunda kalmadığından ilgi çekici olabilir.

Bunları bir araya getirerek, iki dosyadaki iki nesne aşağıdaki gibi belirtilen şekilde birleştirilebilir:

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

'-N' bayrağı jq'ye stdin'den okumamasını söyler, çünkü girdiler buradaki --argfile seçeneklerinden gelir.


2
jq onaylamamıştır --argileiçin--slurpfile
— David Groomes

3

Bu, komutta belirtilen herhangi bir sayıda dosyayı birleştirmek için kullanılabilir:

jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json

veya bu herhangi bir sayıda dosya için

jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.