Làm cách nào để cập nhật một giá trị duy nhất trong tài liệu json bằng jq?


103

Appologies nếu tôi đã bỏ qua một cái gì đó rất rõ ràng; Tôi vừa tìm thấy jqvà đang cố gắng sử dụng nó để cập nhật một giá trị JSON mà không ảnh hưởng đến dữ liệu xung quanh.

Tôi muốn chuyển một curlkết quả vào jq, cập nhật một giá trị và chuyển JSON đã cập nhật thành a curl -X PUT. Cái gì đó như

curl http://example.com/shipping.json | jq '.' field: value | curl -X PUT http://example.com/shipping.json

Cho đến nay tôi đã hack nó cùng nhau bằng cách sử dụng sed, nhưng sau khi xem xét một vài ví dụ về |=toán tử trong jqtôi chắc chắn rằng tôi không cần những điều này.

Đây là một mẫu JSON - tôi sẽ sử dụng cách nào jqđể đặt "local": false, trong khi vẫn giữ nguyên phần còn lại của JSON?

{
  "shipping": {
    "local": true,
    "us": true,
    "us_rate": {
      "amount": "0.00",
      "currency": "USD",
      "symbol": "$"
    }
  }
}

Câu trả lời:


126

Bạn đặt giá trị của một đối tượng bằng =toán tử. |=mặt khác được sử dụng để cập nhật một giá trị. Đó là một sự khác biệt tinh tế nhưng quan trọng. Bối cảnh của các bộ lọc thay đổi.

Vì bạn đang đặt một thuộc tính thành một giá trị không đổi, hãy sử dụng =toán tử.

.shipping.local = false

Chỉ cần lưu ý rằng khi đặt giá trị cho một thuộc tính, nó không nhất thiết phải tồn tại. Bạn có thể thêm các giá trị mới dễ dàng theo cách này.

.shipping.local = false | .shipping.canada = false | .shipping.mexico = true

10
Mẫu này không tốt cho giá trị bình thường. Vì vậy, nếu bạn cần thay đổi giá trị bình thường, bạn cần thêm "với nó, chẳng hạn như .shipping.local = "new place". Vì vậy, toàn bộ lệnh sẽ được curl http://example.com/shipping.json | jq '.shipping.local = "new place"'. Nếu không, bạn sẽ gặp những lỗi lạ.
BMW

8
@BMW cái gì? Ở đây hoàn toàn ổn. Mọi giá trị json hợp lệ đều hợp lệ, điều này chỉ xảy ra với nghĩa đen false. Giá trị không nhất thiết phải là chuỗi.
Jeff Mercado

@BMW OP muốn đặt nó bằng false. Chuyện gì vậy?
SOFe

17

Cập nhật giá trị (đặt .foo.bar thành "giá trị mới"):

jq '.foo.bar = "new value"' file.json

Cập nhật giá trị bằng một biến (đặt .foo.bar thành "hello"):

variable="hello"; jq --arg variable "$variable" '.foo.bar = $variable' file.json

Tôi đã sử dụng điều này làm ví dụ để đổi tên một gói NPM.json thông qua shell và nó hoạt động 100%, cảm ơn.
Machado

2
Điều này không thực sự thay thế nội dung của tệp. Nó chỉ in ra stdout. Bạn sẽ cần lưu stout trở lại tệp để thực hiện thay đổi. Xem stackoverflow.com/a/60744617/1626687
spuder

1

một hàm tương tự với toán tử | = là ánh xạ. bản đồ sẽ phù hợp để tránh yêu cầu của bộ lọc trước đó cho mảng ...

hãy tưởng tượng rằng dữ liệu của bạn là một mảng (rất phổ biến cho ví dụ này)

[
  {
    "shipping": {
      "local": true,
      "us": true,
      "us_rate": {
        "amount": "1.00",
        "currency": "USD",
        "symbol": "$"
      }
    }
  },
  {
    "shipping": {
      "local": true,
      "us": true,
      "us_rate": {
        "amount": "1.00",
        "currency": "USD",
        "symbol": "$"
      }
    }
  }
]

do đó cần phải coi mảng trong mã là:

http://example.com/shipping.json | jq '.[] | .shipping.local = "new place"' | curl -X PUT http://example.com/shipping.json

hoặc sử dụng hàm bản đồ được tạo ra để hoạt động trong mọi phần tử mảng như

http://example.com/shipping.json | jq 'map(.shipping.local = "new place")' | curl -X PUT http://example.com/shipping.json

Quan sát

Vì lợi ích của những người đang học, bạn cũng đã mắc một số sai lầm trong việc sử dụng jq, chỉ cần xem xét rằng nó có "đọc" tham số đầu tiên là chương trình, do đó tất cả các lệnh mong muốn sẽ được đưa vào chuỗi đầu tiên sau khi gọi chương trình.

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.