Câu hỏi Làm thế nào tôi có thể in đẹp JSON trong một tập lệnh shell (Unix)?


Có một kịch bản shell (Unix) để định dạng JSON ở dạng có thể đọc được không?

Về cơ bản, tôi muốn nó biến đổi như sau:

{ "foo": "lorem", "bar": "ipsum" }

... vào một cái gì đó như thế này:

{
    "foo": "lorem",
    "bar": "ipsum"
}

2503


gốc


stackoverflow.com/a/12892039/998291 - shleim
Tôi đã tự quay lại một thời gian ngắn: github.com/exhuma/braindump/tree/master/jsonformat Mã rất đơn giản, sử dụng riêng của python json thư viện, nhưng tôi cũng thêm vào các bức tranh để làm nổi bật cú pháp. - exhuma
Stumbled về điều này nhưng sau đó tìm thấy Json Pretty và tôi khá thích nó. Typekit sử dụng nó trong ví dụ API của họ, vì vậy có một số klout đằng sau nó ^ ^ - Nick Tomlin
Đây là bài đăng trên blog tóm tắt một số phương pháp hay nhất được đề cập trong chuỗi này. Đối với những người thích tldr: liên kết - PhilYoussef
Được cảnh báo: python -m json.tool không phải lúc nào cũng tạo ra JSON hợp lệ. (Gợi ý: 1e1000) - peak


Các câu trả lời:


Với Python 2.6+ bạn có thể thực hiện:

echo '{"foo": "lorem", "bar": "ipsum"}' | python -m json.tool

hoặc, nếu JSON nằm trong một tệp, bạn có thể thực hiện:

python -m json.tool my_json.json

nếu JSON từ một nguồn internet như API, bạn có thể sử dụng

curl http://my_url/ | python -m json.tool

Để thuận tiện trong tất cả các trường hợp này, bạn có thể tạo bí danh:

alias prettyjson='python -m json.tool'

Để thuận tiện hơn với cách gõ nhiều hơn một chút để chuẩn bị sẵn sàng:

prettyjson_s() {
    echo "$1" | python -m json.tool
}

prettyjson_f() {
    python -m json.tool "$1"
}

prettyjson_w() {
    curl "$1" | python -m json.tool
}

cho tất cả các trường hợp trên. Bạn có thể đặt nó vào .bashrc và nó sẽ có sẵn mỗi lần trong trình bao. Gọi nó như prettyjson_s '{"foo": "lorem", "bar": "ipsum"}'.


3740



Bạn có thể ống lên pygmentize -l javascript để có được đầu ra màu cú pháp trong dòng lệnh của bạn. Chỉnh sửa: Nếu bạn đã cài đặt pygments. - Shrikant Sharat
Một câu trả lời tuyệt vời, chỉ thận trọng tôi có với nó là nó làm sắp xếp các khóa trên đầu ra - mà bạn có thể cần phải biết. - Chris Nash
Trong myy .vimrc "nnoremap <f5>:%! Python -m json.tool <CR>: w <CR>" - imwilsonxu
Điều này dường như để thoát khỏi các ký tự Unicode thành \ uXXXX, đây có thể là một bất lợi. - user1071136
Tôi đã tạo bí danh: alias pretty='python -mjson.tool | pygmentize -l json để tôi có thể chạy: command params | pretty. Hi vọng điêu nay co ich. PS: Nếu bất cứ ai quản lý để mở rộng này để a) loại bỏ đầu ra curl Tôi nhìn thấy mọi thời gian và / hoặc b) KHÔNG sắp xếp các phím json; xin vui lòng cho tôi biết, tôi sẽ rất biết ơn. - Clint Eastwood


Bạn có thể dùng: jq

Nó rất đơn giản để sử dụng và nó hoạt động tuyệt vời! Nó có thể xử lý các cấu trúc JSON rất lớn, bao gồm cả các luồng. Bạn có thể tìm hướng dẫn của họ đây.

Đây là một ví dụ:

$ jq . <<< '{ "foo": "lorem", "bar": "ipsum" }'
{
  "bar": "ipsum",
  "foo": "lorem"
}

Hay nói cách khác:

$ echo '{ "foo": "lorem", "bar": "ipsum" }' | jq .
{
  "bar": "ipsum",
  "foo": "lorem"
}

690



Cũng có một --sort-keys tùy chọn, điều này hữu ích trong một số trường hợp. - Matthew Flaschen
Làm việc với curl: curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.' - Hover Ruan
Câu trả lời này là khó hiểu vì tối nghĩa <<< toán tử. Tại sao không chỉ sử dụng echo '{ "foo": "lorem", "bar": "ipsum" }' | jq . cho ví dụ? - Meekohi
"jq." là tuyệt vời như một máy in khá, nhưng nó đi kèm với một caveat: jq (lên đến và bao gồm cả jq phiên bản 1.5) sẽ thay đổi các giá trị rất lớn và rất nhỏ vì nó phân tích các giá trị số như IEEE 754 64-bit giá trị. Để kiểm tra xem máy in đẹp yêu thích của bạn có cùng vấn đề hay không, hãy thử giá trị này: 1e1000. Lưu ý rằng python -mjson.tool thất bại trong bài kiểm tra này ở chỗ nó tạo ra Infinity, thậm chí không phải là JSON. - peak
@Meekohi thay thế là "sử dụng không cần thiết của echo". Rất vui khi tìm thấy <<< nhà điều hành - chính xác những gì tôi đang tìm kiếm. - jchook


Tôi sử dụng đối số "không gian" của JSON.stringify để in đẹp JSON bằng JavaScript.

Ví dụ:

// Indent with 4 spaces
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, 4);

// Indent with tabs
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, '\t');

Từ dòng lệnh Unix với các nút, chỉ định json trên dòng lệnh:

$ node -e "console.log(JSON.stringify(JSON.parse(process.argv[1]), null, '\t'));" \
  '{"foo":"lorem","bar":"ipsum"}'

Trả về:

{
    "foo": "lorem",
    "bar": "ipsum"
}

Từ dòng lệnh Unix với Node.js, chỉ định một tên tệp có chứa JSON và sử dụng một thụt lề của bốn dấu cách:

$ node -e "console.log(JSON.stringify(JSON.parse(require('fs') \
      .readFileSync(process.argv[1])), null, 4));"  filename.json

Sử dụng đường ống:

echo '{"foo": "lorem", "bar": "ipsum"}' | node -e \
"\
 s=process.openStdin();\
 d=[];\
 s.on('data',function(c){\
   d.push(c);\
 });\
 s.on('end',function(){\
   console.log(JSON.stringify(JSON.parse(d.join('')),null,2));\
 });\
"

358



Để gỡ lỗi các đối tượng trong Node.js, bạn nên sử dụng sys.inspect () thay vì JSON.stringify (). Đây là lý do tại sao: markhansen.co.nz/inspecting-with-json-stringify - Gurpartap Singh
Đã bỏ phiếu. OP là về một "* nix dòng lệnh script" và câu trả lời này là một bối cảnh khác nhau. - danorton
@danorton: JS có thể được sử dụng từ dòng lệnh thông qua node.js và các giải pháp tương tự khác. - calvinf
Không cần bàn điều khiển: node -p "JSON.stringify(JSON.parse(process.argv[1]), null, '\t');" cũng xuất kết quả ra STDOUT. - Julian D.
Nó sucks rằng kịch bản là khác nhau cho một tên tập tin so với stdin - Lukasz Wiktor


Tôi đã viết một công cụ có một trong các trình định dạng "khoảng trống thông minh" tốt nhất hiện có. Nó tạo ra nhiều đầu ra dễ đọc hơn và ít tiết hơn so với hầu hết các tùy chọn khác ở đây.

underscore-cli

Đây là những gì "khoảng trắng thông minh" trông giống như:

Tôi có thể hơi thiên vị, nhưng đó là một công cụ tuyệt vời để in và thao tác dữ liệu JSON từ dòng lệnh. Đó là siêu thân thiện để sử dụng và có trợ giúp dòng lệnh / tài liệu mở rộng. Đó là một con dao quân đội Thụy Sĩ mà tôi sử dụng cho 1001 nhiệm vụ nhỏ khác nhau mà sẽ gây ngạc nhiên đáng ngạc nhiên để làm bất kỳ cách nào khác.

Trường hợp sử dụng mới nhất: Chrome, bảng điều khiển Dev, tab Mạng, xuất tất cả dưới dạng tệp HAR, "cat site.har | gạch dưới chọn '.url' --outfmt text | grep mydomain"; bây giờ tôi có danh sách theo thứ tự thời gian của tất cả các lần tìm nạp URL được thực hiện trong quá trình tải trang web của công ty tôi.

In khá dễ dàng:

underscore -i data.json print

Điều tương tự:

cat data.json | underscore print

Tương tự, rõ ràng hơn:

cat data.json | underscore print --outfmt pretty

Công cụ này là dự án đam mê hiện tại của tôi, vì vậy nếu bạn có bất kỳ yêu cầu tính năng nào, có một cơ hội tốt để tôi giải quyết chúng.


321



Tôi cũng đã cập nhật ~ / .bash_profile của mình để có dòng sau: alias underscor = 'underscore print --outfmt pretty' bây giờ tôi chỉ có thể làm curl example.com/result.json | gạch dưới và vẫn sử dụng dấu gạch dưới để định dạng khác - Gal Bracha
Cảm ơn Dave! Công cụ là tốt! alias pretty-json = "underrsore pretty" và đầu ra curl làm hài lòng một mắt - Maxim Ponomarev
Công cụ định dạng tuyệt vời, chỉ một lưu ý: chuyển tiếp đầu ra tới một tệp (với -o tùy chọn hoặc với > ) chỉ hoạt động với gạch dưới in. gạch dưới khá lưu tệp có dấu hiệu định dạng màu được chèn vào, như sau: [32m, [33m, [39m cùng với một số không thể in được trước mỗi người trong số họ, điều này làm cho JSON không hợp lệ. Tuy nhiên, gạch dưới in một mình không thêm bất kỳ thứ gì vào một tệp và thực hiện công việc định dạng của nó một cách hoàn hảo. - tiurin
tôi yêu jq nhưng điều này làm việc tuyệt vời cho "JSON" của tôi mà không có các khóa được trích dẫn kép. - Bluu
@ DaveDopson cảm ơn vì công cụ tuyệt vời !! Gonna hãy thử sử dụng nó cùng với jsonselect.org/#tryit ... - mycargus


Tôi thường chỉ làm:

echo '{"test":1,"test2":2}' | python -mjson.tool

Và để lấy dữ liệu đã chọn (trong trường hợp này, giá trị "test"):

echo '{"test":1,"test2":2}' | python -c 'import sys,json;data=json.loads(sys.stdin.read()); print data["test"]'

Nếu dữ liệu JSON nằm trong một tệp:

python -mjson.tool filename.json

Nếu bạn muốn làm tất cả trong một đi với curl trên dòng lệnh bằng mã thông báo xác thực:

curl -X GET -H "Authorization: Token wef4fwef54te4t5teerdfgghrtgdg53" http://testsite/api/ | python -mjson.tool

168



python> = 2.6 bắt buộc - dim
nếu json là nghĩa vụ phải đến trực tiếp froma http api này cũng là một công cụ tốt đẹp thực hiện trong python: github.com/jkbr/httpie - Florian
Nếu bạn đã cài đặt nút (và không quan tâm đến đầu ra kiểu YAML) thì cũng có gói này: rafeca.com/prettyjson để bạn có thể kết thúc | prettyjson - Iolo
Như đã nói ở trên, một trong những vấn đề với python -mjson.tool như một máy in khá JSON là nó không phải lúc nào cũng phát ra JSON. Ví dụ. 1e1000 trở thành Infinity (cho dù sử dụng python 2.x hoặc 3.x). 'jq.' luôn sản xuất JSON, nhưng nó không đảm bảo rằng các giá trị rất lớn (hoặc rất nhỏ) được bảo toàn chính xác. - peak


Nhờ có các con trỏ rất hữu ích của J.F. Sebastian, đây là một kịch bản được tăng cường một chút mà tôi đã đưa ra:

#!/usr/bin/python

"""
Convert JSON data to human-readable form.

Usage:
  prettyJSON.py inputFile [outputFile]
"""

import sys
import simplejson as json


def main(args):
    try:
        if args[1] == '-':
            inputFile = sys.stdin
        else:
            inputFile = open(args[1])
        input = json.load(inputFile)
        inputFile.close()
    except IndexError:
        usage()
        return False
    if len(args) < 3:
        print json.dumps(input, sort_keys = False, indent = 4)
    else:
        outputFile = open(args[2], "w")
        json.dump(input, outputFile, sort_keys = False, indent = 4)
        outputFile.close()
    return True


def usage():
    print __doc__


if __name__ == "__main__":
    sys.exit(not main(sys.argv))

82



Khi các giá trị được nạp vào từ điển, thứ tự bị mất: bình thường dict các đối tượng không có thứ tự xác định. Thử json.dumps(json.loads('{"b": 1, "a": 2}'), sort_keys=False) và bạn sẽ thấy họ đổi chỗ. Để khắc phục, hãy nhập OrderedDict và load đi qua object_pairs_hook=OrderedDict. - icktoofay
Bạn có thể thay đổi tập lệnh để đọc từ đầu vào chuẩn với điều này: inputFile = sys.stdin. Điều này cho phép bạn thêm nội dung vào kịch bản như sau: curl http://somewhere.com/foo.json | pp_json.py - Gabe Johnson
Và để tránh phân loại với nhận xét của @ icktoofay, hãy nhập OrderedDict như sau: from collections import OrderedDict. - Hugo
Cảm ơn @icktoofay. Điều này cho phép tôi tạo hàm vim sau: com! FormatJSON %!python -c "from collections import OrderedDict; import sys; import json; j = json.load(sys.stdin, object_pairs_hook=OrderedDict); json.dump(j, sys.stdout, sort_keys=False, indent=4, separators=(',', ': '))"  Lưu ý rằng các dấu tách phải được đặt là (',', ':') để tránh khoảng trắng dấu sau được thêm vào: bugs.python.org/issue16333 - blindsnowmobile
Đoạn trích tuyệt vời! Tôi đã sử dụng sort_keys = True thay vào đó, bởi vì tôi muốn sử dụng nó để so sánh các tệp json và nó hoạt động như một sự quyến rũ. - JL Peyret


Trên * nix, đọc từ stdin và viết để stdout hoạt động tốt hơn:

#!/usr/bin/env python
"""
Convert JSON data to human-readable form.

(Reads from stdin and writes to stdout)
"""

import sys
try:
    import simplejson as json
except:
    import json

print json.dumps(json.loads(sys.stdin.read()), indent=4)
sys.exit(0)

Đặt cái này vào một tập tin (tôi đặt tên là "prettyJSON" sau AnC's câu trả lời) trong PATH của bạn và chmod +x nó, và bạn tốt để đi.


66



Thật vậy, sử dụng stdin / stdout là linh hoạt hơn và đơn giản hơn nhiều. Cảm ơn đã chỉ ra điều đó. - AnC
Đối với các chương trình mong đợi một tệp được đặt tên, hãy sử dụng / dev / stdin, ditto for out và err. - dvogel
FYI fileinput.input() đọc từ stdin nếu không có tệp nào được đưa ra tại dòng lệnh. Thí dụ - jfs
fileinput.input () không thể xử lý tốt với các tệp không có dòng mới ở cuối, lần cuối tôi đã kiểm tra. - Zachary Vance
stdin.read () không thể dừng lại ... làm thế nào tôi có thể ngăn chặn điều này ??? - xiaoweiz


Với Perl, hãy sử dụng mô-đun CPAN JSON::XS. Nó cài đặt một công cụ dòng lệnh json_xs.

Xác thực:

json_xs -t null < myfile.json

Chuẩn bị tệp JSON src.jsonđến pretty.json:

< src.json json_xs > pretty.json

Nếu bạn không có json_xs, thử json_pp . "pp" là dành cho "perl tinh khiết" - công cụ này chỉ được thực hiện trong Perl, không có ràng buộc với thư viện C bên ngoài (đó là điều mà XS viết tắt là "Hệ thống mở rộng" của Perl).


65



Dường như trở thành tiêu chuẩn với Cygwin! - Janus Troelsen
json_pp có thể được sử dụng trong cùng một cách và có lẽ là dễ dàng nhất được cài đặt trên hệ thống của bạn (trên Debian nó nằm trong gói 'perl'). - MichielB
FYI, trên hệ thống Mac OS X 10.9 của tôi, json_pp có sẵn tự động. - Gregg Williams
Hoặc, trang dành cho "in đẹp" .. - FliiFe
-t null đưa cho tôi null: không phải là toformat hợp lệ... nhưng để nó hoạt động lộng lẫy. Cảm ơn. - Lucas


Nếu bạn sử dụng npm và Node.js, bạn có thể làm npm install -g json và sau đó đặt lệnh qua json. Làm json -h để có được tất cả các tùy chọn. Nó cũng có thể kéo ra các trường cụ thể và tô màu đầu ra bằng -i.

curl -s http://search.twitter.com/search.json?q=node.js | json

64



Đây là câu trả lời yêu thích của tôi ở đây. - Jon Deaton


JSON Ruby Gem được đóng gói với một kịch bản lệnh shell để làm cho JSON dễ dàng hơn:

sudo gem install json
echo '{ "foo": "bar" }' | prettify_json.rb

Tải xuống tập lệnh: gist.github.com/3738968


63



Lưu ý rằng giải pháp này giải mã chuỗi "\ uxxxx" unicode, không giống như trình tự Python với json.tool. Tuy nhiên, nó cũng có vẻ có giới hạn chiều sâu làm tổ (nesting of 20 is too deep (JSON::NestingError)). - a3nm
trên Ubuntu bạn có thể làm: sudo apt-get install ruby-json-pure thay vì gem install - Janus Troelsen
`` `eric-mbp: ~ ericstob $ sudo gem install json Mật khẩu: Tìm nạp: json-1.7.3.gem (100%) Xây dựng tiện ích mở rộng gốc. Quá trình này có thể mất một lúc ... Cài đặt thành công đá quý json-1.7.3 1 Cài đặt tài liệu ri cho json-1.7.3 ... Cài đặt tài liệu hướng dẫn cho json-1.7.3 ... eric-mbp: ~ ericstob $ prettify_json .rb -bash: prettify_json.rb: không tìm thấy lệnh - Eric Hartford
có thể bạn có thể đăng nội dung của prettify_json.rb? - Andrew
Bạn có thể tải xuống tập lệnh, di chuyển tập lệnh đến ~/bin thư mục (chắc chắn rằng nó trong PATH của bạn) đổi tên prettify_json.rbđến ppj và chạy chmod +x ppj. Bây giờ bạn có thể làm một cái gì đó như curl www.jsonsring.com/something.json | ppj - Uri


Nó không phải là quá đơn giản với một cách bản địa với các công cụ jq.

Ví dụ:

cat xxx | jq .

56



CẢNH BÁO: jq mã hóa các số như IEEE 754 64-bit nổi, và do đó biểu diễn của chúng có thể thay đổi. Độ chính xác của các con số rất nhỏ và rất lớn có khả năng bị mất. Để kiểm tra xem máy in đẹp yêu thích của bạn có cùng vấn đề hay không, hãy thử giá trị này: 1e1000. - peak
hoặc đơn giản: jq . file.json ; nhưng cũng cat file.json | jq (không có bộ lọc .) cũng hoạt động. (trên ubuntu / linux; ymmv trên nền tảng) - michael