Người gầy
jq -r '(.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv'
hoặc là:
jq -r '(.[0] | keys_unsorted) as $keys | ([$keys] + map([.[ $keys[] ]])) [] | @csv'
Các chi tiết
Qua một bên
Việc mô tả chi tiết rất phức tạp bởi vì jq là hướng dòng, có nghĩa là nó hoạt động trên một chuỗi dữ liệu JSON, thay vì một giá trị duy nhất. Luồng JSON đầu vào được chuyển đổi thành một số kiểu nội bộ được chuyển qua các bộ lọc, sau đó được mã hóa trong luồng đầu ra ở cuối chương trình. Loại nội bộ không được JSON mô hình hóa và không tồn tại dưới dạng một loại được đặt tên. Nó dễ dàng được chứng minh nhất bằng cách kiểm tra đầu ra của một chỉ mục trống ( .[]
) hoặc toán tử dấu phẩy (kiểm tra trực tiếp nó có thể được thực hiện bằng trình gỡ lỗi, nhưng điều đó sẽ là về các kiểu dữ liệu nội bộ của jq, chứ không phải là các kiểu dữ liệu khái niệm đằng sau JSON) .
$ jq -c '. []' <<< '["a", "b"]'
"a"
"b"
$ jq -cn '"a", "b"'
"a"
"b"
Lưu ý rằng đầu ra không phải là một mảng (sẽ là ["a", "b"]
). Đầu ra thu gọn ( -c
tùy chọn) cho thấy mỗi phần tử mảng (hoặc đối số của ,
bộ lọc) trở thành một đối tượng riêng biệt trong đầu ra (mỗi phần tử nằm trên một dòng riêng biệt).
Một luồng giống như một JSON-seq , nhưng sử dụng các dòng mới thay vì RS làm dấu phân tách đầu ra khi được mã hóa. Do đó, kiểu nội bộ này được gọi bằng thuật ngữ chung "chuỗi" trong câu trả lời này, với "luồng" được dành riêng cho đầu vào và đầu ra được mã hóa.
Cấu tạo bộ lọc
Các khóa của đối tượng đầu tiên có thể được trích xuất bằng:
.[0] | keys_unsorted
Các chìa khóa thường sẽ được giữ theo thứ tự ban đầu, nhưng không đảm bảo việc bảo toàn thứ tự chính xác. Do đó, chúng sẽ cần được sử dụng để lập chỉ mục các đối tượng để nhận các giá trị theo cùng một thứ tự. Điều này cũng sẽ ngăn các giá trị nằm trong cột sai nếu một số đối tượng có thứ tự khóa khác nhau.
Để vừa xuất các khóa dưới dạng hàng đầu tiên và làm cho chúng có sẵn để lập chỉ mục, chúng được lưu trữ trong một biến. Giai đoạn tiếp theo của đường ống sau đó tham chiếu đến biến này và sử dụng toán tử dấu phẩy để thêm tiêu đề vào luồng đầu ra.
(.[0] | keys_unsorted) as $keys | $keys, ...
Biểu thức sau dấu phẩy có một chút liên quan. Toán tử chỉ mục trên một đối tượng có thể nhận một chuỗi các chuỗi (ví dụ "name", "value"
), trả về một chuỗi các giá trị thuộc tính cho các chuỗi đó. $keys
là một mảng, không phải là một chuỗi, vì vậy []
được áp dụng để chuyển đổi nó thành một chuỗi,
$keys[]
sau đó có thể được chuyển cho .[]
.[ $keys[] ]
Điều này cũng tạo ra một chuỗi, vì vậy hàm tạo mảng được sử dụng để chuyển đổi nó thành một mảng.
[.[ $keys[] ]]
Biểu thức này sẽ được áp dụng cho một đối tượng. map()
được sử dụng để áp dụng nó cho tất cả các đối tượng trong mảng bên ngoài:
map([.[ $keys[] ]])
Cuối cùng cho giai đoạn này, điều này được chuyển đổi thành một chuỗi để mỗi mục trở thành một hàng riêng biệt trong đầu ra.
map([.[ $keys[] ]])[]
Tại sao lại nhóm chuỗi thành một mảng trong mảng map
duy nhất để bỏ nhóm bên ngoài? map
tạo ra một mảng; .[ $keys[] ]
tạo ra một chuỗi. Việc áp dụng map
cho chuỗi từ .[ $keys[] ]
sẽ tạo ra một mảng các chuỗi giá trị, nhưng vì chuỗi không phải là kiểu JSON, vì vậy thay vào đó bạn sẽ nhận được một mảng phẳng chứa tất cả các giá trị.
["NSW","AU","state","New South Wales","AB","CA","province","Alberta","ABD","GB","council area","Aberdeenshire","AK","US","state","Alaska"]
Các giá trị từ mỗi đối tượng cần được giữ riêng biệt để chúng trở thành các hàng riêng biệt trong kết quả cuối cùng.
Cuối cùng, trình tự được chuyển qua trình @csv
định dạng.
Luân phiên
Các mục có thể được tách ra muộn hơn là sớm. Thay vì sử dụng toán tử dấu phẩy để nhận một chuỗi (chuyển một chuỗi làm toán hạng bên phải), chuỗi tiêu đề ( $keys
) có thể được bao bọc trong một mảng và +
được sử dụng để nối thêm mảng giá trị. Điều này vẫn cần được chuyển đổi thành một chuỗi trước khi được chuyển đến @csv
.
json2csv
ở stackoverflow.com/questions/57242240/…