Chọn các đối tượng dựa trên giá trị của biến trong đối tượng bằng jq


236

Tôi có tập tin json sau:

{
    "FOO": {
        "name": "Donald",
        "location": "Stockholm"
    },
    "BAR": {
        "name": "Walt",
        "location": "Stockholm"
    },
    "BAZ": {
        "name": "Jack",
        "location": "Whereever"
    }
}

Tôi đang sử dụng jq và muốn lấy các phần tử "tên" của các đối tượng trong đó 'vị trí' là 'Stockholm'.

Tôi biết tôi có thể nhận được tất cả các tên bằng cách

cat json | jq .[] | jq ."name"
"Jack"
"Walt"
"Donald"

Nhưng tôi không thể tìm ra cách chỉ in một số đối tượng nhất định, với giá trị của khóa phụ (ở đây "location" : "Stockholm").

Câu trả lời:


341

Được chuyển thể từ bài đăng này về Xử lý JSON bằng jq , bạn có thể sử dụng select(bool)như thế này:

$ jq '.[] | select(.location=="Stockholm")' json
{
  "location": "Stockholm",
  "name": "Walt"
}
{
  "location": "Stockholm",
  "name": "Donald"
}

30
Làm thế nào tôi có được cha mẹ 'FOO', 'BAR', 'BAZ'?
spazm

184

Để có được một luồng chỉ các tên:

$ jq '.[] | select(.location=="Stockholm") | .name' json

sản xuất:

"Donald"
"Walt"

Để có được một luồng các cặp tương ứng (tên khóa, "tên"), hãy xem xét:

$ jq -c 'to_entries[]
        | select (.value.location == "Stockholm")
        | [.key, .value.name]' json

Đầu ra:

["FOO","Donald"]
["BAR","Walt"]

Anh ta muốn toàn bộ đối tượng dựa trên vị trí: "Tôi không thể tìm ra cách chỉ in một số đối tượng nhất định, với giá trị của khóa phụ"
fo.

2
Bạn không cần đường ống sau khi chọn: $ jq '. [] | chọn (.location == "Stockholm"). name 'json
Deepak

Tạo namebiến khóa (sử dụng hàm shell với $1tham số) không hoạt động : termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'. Tôi gọi nó như thế cool_fn Name1. Tuy nhiên, điều này hoạt động:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
Timo

Đây là giải pháp nếu bạn thích nó biến.
Timo

27

Tôi đã có một câu hỏi liên quan tương tự: Điều gì sẽ xảy ra nếu bạn muốn định dạng đối tượng ban đầu trở lại (với các tên chính, ví dụ FOO, BAR)?

Jq cung cấp to_entriesfrom_entriesđể chuyển đổi giữa các đối tượng và mảng cặp giá trị khóa. Điều đó cùng với mapxung quanh lựa chọn

Các hàm này chuyển đổi giữa một đối tượng và một mảng các cặp khóa-giá trị. Nếu to_entries được truyền vào một đối tượng, thì với mỗi mục nhập k: v trong đầu vào, mảng đầu ra bao gồm {"key": k, "value": v}.

from_entries thực hiện chuyển đổi ngược lại và with_entries (foo) là một cách viết tắt của to_entries | bản đồ (foo) | from_entries, hữu ích để thực hiện một số thao tác cho tất cả các khóa và giá trị của một đối tượng. from_entries chấp nhận khóa, Khóa, tên, Tên, giá trị và Giá trị làm khóa.

jq15 < json 'to_entries | map(select(.value.location=="Stockholm")) | from_entries'

{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

Sử dụng tốc with_entrieský, điều này trở thành:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

1
Một điều khiến tôi khó chịu là bạn cần nhớ rằng khi sử dụng with_entries(), bạn thường muốn sử dụng .valuetrong selectmệnh đề. Điều này là do to_entriesmacro chuyển đổi các mục đã cho thành .key.valueghép, điều này cũng xảy ra với with_entries.
Jaakko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.