Pytanie Jak mogę wydrukować JSON w skrypcie powłoki (Unix)?


Czy istnieje skrypt powłoki (Unix) do sformatowania JSON w formie czytelnej dla człowieka?

Zasadniczo chcę, aby przekształcić następujące:

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

... w coś takiego:

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

2503


pochodzenie


stackoverflow.com/a/12892039/998291 - shleim
Szybko przetoczyłem się na bok: github.com/exhuma/braindump/tree/master/jsonformat Kod jest bardzo prosty, używając samego Pythona json biblioteki, ale dodałem także pygmenty, aby uzyskać podświetlanie składni. - exhuma
Natknąłem się na to, ale potem znalazłem Json Pretty i bardzo mi się to podoba. Typekit używa go w swoich przykładach API, więc jest za tym jakiś klout ^^ - Nick Tomlin
Oto blog opisujący niektóre z najlepszych metod wymienionych w tym wątku. Dla tych, którzy wolą tldr: połączyć - PhilYoussef
Być ostrzeżonym: python -m json.tool nie zawsze generuje prawidłowy JSON. (Wskazówka: 1e1000) - peak


Odpowiedzi:


W Pythonie 2.6+ możesz po prostu:

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

lub jeśli JSON jest w pliku, możesz zrobić:

python -m json.tool my_json.json

jeśli JSON pochodzi ze źródła internetowego, takiego jak API, możesz użyć

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

Dla wygody we wszystkich tych przypadkach możesz utworzyć alias:

alias prettyjson='python -m json.tool'

Aby uzyskać jeszcze większą wygodę i trochę więcej pisania, aby przygotować go:

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

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

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

dla wszystkich powyższych przypadków. Możesz to podać .bashrc i będzie dostępny za każdym razem w powłoce. Wywołaj to jak prettyjson_s '{"foo": "lorem", "bar": "ipsum"}'.


3740



Możesz to potoczyć pygmentize -l javascript aby uzyskać kolorowe wyjście składni w linii poleceń. Edytować: Jeśli masz zainstalowane pygmenty. - Shrikant Sharat
Świetna odpowiedź, tylko ostrożność, którą mam z tym, jest robi sortuj klucze na wyjściu - o czym być może będziesz musiał pamiętać. - Chris Nash
W myy .vimrc "nnoremap <f5>:%! Python -m json.tool <CR>: w <CR>" - imwilsonxu
Wydaje się, że unikamy znaków Unicode w \ uXXXX, co może być wadą. - user1071136
Stworzyłem alias: alias pretty='python -mjson.tool | pygmentize -l json więc mogę po prostu uruchomić: command params | pretty. Mam nadzieję że to pomoże. PS: Jeśli ktokolwiek zdoła rozszerzyć to do a) usuń curl-output widzę za każdym razem i / lub b) NIE sortuj klawiszy json; proszę daj mi znać, będę bardzo wdzięczny. - Clint Eastwood


Możesz użyć: jq

Jest bardzo prosty w użyciu i działa świetnie! Może obsługiwać bardzo duże struktury JSON, w tym strumienie. Możesz znaleźć ich samouczki tutaj.

Oto przykład:

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

Lub innymi słowy:

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

690



Istnieje również --sort-keys opcja, co jest pomocne w niektórych przypadkach. - Matthew Flaschen
Praca z curl: curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.' - Hover Ruan
Ta odpowiedź jest myląca z powodu niejasnych operator <<<. Dlaczego po prostu nie skorzystać echo '{ "foo": "lorem", "bar": "ipsum" }' | jq . na przykład? - Meekohi
"jq." jest świetny jako ładna drukarka, ale zawiera zastrzeżenie: jq (do wersji jq włącznie 1.5) zmieni wartości bardzo dużych i bardzo małych liczb, ponieważ parsuje wartości liczbowe jako 64-bitowe wartości IEEE 754. Aby sprawdzić, czy twoja ulubiona ładna drukarka ma ten sam problem, wypróbuj tę wartość: 1e1000. Zauważ, że python -mjson.tool źle to testuje, ponieważ produkuje Nieskończoność, która nie jest nawet JSON. - peak
@Meekohi alternatywą jest "niepotrzebne użycie echa". Super szczęśliwy, że znalazłem <<< operator - dokładnie to, czego szukałem. - jchook


Używam argumentu "space" z JSON.stringify całkiem wydrukować JSON w JavaScript.

Przykłady:

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

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

Z wiersza poleceń systemu Unix z nodejs, określając json w wierszu poleceń:

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

Zwroty:

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

Z wiersza poleceń systemu Unix za pomocą Node.js, określając nazwę pliku zawierającego JSON i używając wcięć z czterema spacjami:

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

Korzystanie z potoku:

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



Do debugowania obiektów w Node.js powinieneś naprawdę użyć sys.inspect () zamiast JSON.stringify (). Dlatego: markhansen.co.nz/inspecting-with-json-stringify - Gurpartap Singh
Wycofane. OP dotyczy "skryptu wiersza poleceń * nix", a ta odpowiedź to inny kontekst. - danorton
@danorton: JS może być używany z wiersza poleceń za pośrednictwem node.js i innych podobnych rozwiązań. - calvinf
Nie potrzebujesz konsoli: node -p "JSON.stringify(JSON.parse(process.argv[1]), null, '\t');" również wyprowadza wynik do STDOUT. - Julian D.
To jest do bani, że skrypt jest inny dla nazwy pliku niż stdin - Lukasz Wiktor


Napisałem narzędzie, które ma jeden z najlepszych formaterów "inteligentnych białych znaków". Zapewnia bardziej czytelny i mniej szczegółowy wynik niż większość innych opcji tutaj.

podkreślenie-cli

Oto jak wygląda "sprytna biała przestrzeń":

Mogę być nieco stronniczy, ale jest to niesamowite narzędzie do drukowania i manipulowania danymi JSON z wiersza poleceń. Jest bardzo przyjazny w użyciu i posiada obszerną pomoc / dokumentację w wierszu poleceń. To szwajcarski scyzoryk, którego używam do wykonania 1001 różnych drobnych zadań, które byłyby zaskakująco irytujące w jakikolwiek inny sposób.

Najnowszy przypadek użycia: Chrome, konsola Dev, karta Sieć, eksportuj wszystko jako plik HAR, "cat site.har | podkreślenie wybierz" .url "--outfmt text | grep mydomain"; teraz mam chronologicznie uporządkowaną listę wszystkich pobrań adresów URL wykonanych podczas ładowania strony mojej firmy.

Ładne drukowanie jest łatwe:

underscore -i data.json print

Ta sama rzecz:

cat data.json | underscore print

To samo, bardziej wyraźne:

cat data.json | underscore print --outfmt pretty

To narzędzie jest moim obecnym projektem pasyjnym, więc jeśli masz jakieś prośby o funkcję, jest duża szansa, że ​​się do nich odezwę.


321



Zaktualizowałem również ~ / .bash_profile, aby uzyskać następujący wiersz: alias underscor = 'underscore print - outfmt pretty' Teraz mogę po prostu zrobić curl example.com/result.json | underscor i nadal używać podkreślenia dla innego formatowania - Gal Bracha
Dzięki, Dave! Narzędzie jest dobre! alias pretty-json = "underrsore pretty" i wyjście curl miłe dla oka - Maxim Ponomarev
Doskonałe narzędzie do formatowania, tylko jedna uwaga: przekazywanie danych wyjściowych do pliku (z użyciem -o opcja lub z > ) działa tylko z podkreślenie wydruku. podkreślają ładne zapisuje plik z wstawionymi znakami formatowania kolorów, coś jak: [32m, [33m, [39m wraz z niektórymi niedrukowanymi przed każdym z nich, co powoduje, że JSON jest nieważny. Jednak, podkreślenie wydruku sam nie dodaje niczego do pliku i doskonale wykonuje swoje zadanie formatowania. - tiurin
kocham jq ale to zadziałało znakomicie dla mojego "JSON", który nie miał podwójnie cytowanych kluczy. - Bluu
@DaveDopson dzięki za wspaniałe narzędzie !! Spróbuję go użyć obok jsonselect.org/#tryit ... - mycargus


Zwykle po prostu:

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

I aby pobrać wybrane dane (w tym przypadku "wartość testu"):

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

Jeśli dane JSON znajdują się w pliku:

python -mjson.tool filename.json

Jeśli chcesz zrobić to wszystko za jednym razem curl w linii poleceń za pomocą tokena uwierzytelniania:

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

168



python> = 2.6 wymagany - dim
jeśli json ma pochodzić bezpośrednio z api api, to jest to również fajne narzędzie zaimplementowane w pythonie: github.com/jkbr/httpie - Florian
Jeśli masz zainstalowany węzeł (i nie masz nic przeciwko wyjściu w stylu YAML), jest też ten pakiet: rafeca.com/prettyjson więc możesz zakończyć zwijanie za pomocą | prettyjson - Iolo
Jak wspomniano powyżej, jeden z problemów z python -mjson.tool jako że ładna drukarka JSON jest taka, że ​​nie zawsze emituje JSON. Na przykład. 1e1000 staje się nieskończonością (bez względu na to, czy używasz Pythona 2.x, czy 3.x). "jq." zawsze wytwarza JSON, ale nie gwarantuje, że bardzo duże (lub bardzo małe wartości) są dokładnie zachowane. - peak


Dzięki bardzo pomocnym wskazówkom J.F. Sebastiana, oto nieco ulepszony skrypt, który wymyśliłem:

#!/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



Gdy wartości są ładowane do słownika, kolejność jest tracona: normalna dict obiekty nie mają zdefiniowanego porządku. Próbować json.dumps(json.loads('{"b": 1, "a": 2}'), sort_keys=False) a przekonasz się, że i tak są zamienione. Aby to naprawić, zaimportuj OrderedDict i load przechodzący object_pairs_hook=OrderedDict. - icktoofay
Możesz zmienić skrypt, aby odczytać ze standardowego wejścia: inputFile = sys.stdin. Pozwala to na potokowanie skryptu w taki sposób: curl http://somewhere.com/foo.json | pp_json.py - Gabe Johnson
Aby uniknąć sortowania za pomocą komentarza @ icktoofay, zaimportuj polecenie OrderedDict w ten sposób: from collections import OrderedDict. - Hugo
Dzięki @icktoofay. To pozwoliło mi stworzyć następującą funkcję vim: 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=(',', ': '))"  Zauważ, że separatory muszą być ustawione jako (',', ':'), aby uniknąć dodawania spacji: bugs.python.org/issue16333 - blindsnowmobile
Świetny fragment! Użyłem sort_keys = True zamiast tego, ponieważ chcę użyć tego do porównania plików json i działa jak urok. - JL Peyret


On * nix, czytanie ze standardowego wejścia i pisania na stdout działa lepiej:

#!/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)

Umieść to w pliku (nazwałem moją "prettyJSON" po) AnCodpowiedź) w Twojej PATH i chmod +x to, i jesteś dobry, aby iść.


66



Rzeczywiście, użycie stdin / stdout jest o wiele bardziej elastyczne i proste. Dziękuję za wskazanie. - AnC
Dla programów, które oczekują nazwanego pliku, użyj / dev / stdin, ditto dla out i err. - dvogel
FYI fileinput.input() czyta ze stdin, jeśli w wierszu poleceń nie ma żadnych plików. Przykład - jfs
fileinput.input () nie radzi sobie dobrze z plikami bez nowej linii na końcu, kiedy ostatnio sprawdzałem. - Zachary Vance
stdin.read () nie może przestać ... jak mogę to zatrzymać ??? - xiaoweiz


W Perlu użyj modułu CPAN JSON::XS. Instaluje narzędzie wiersza poleceń json_xs.

Uprawomocnić:

json_xs -t null < myfile.json

Upiększ plik JSON src.jsondo pretty.json:

< src.json json_xs > pretty.json

Jeśli nie masz json_xs, próbować json_pp . "pp" jest dla "czystego perla" - narzędzie jest zaimplementowane tylko w Perlu, bez wiązania z zewnętrzną biblioteką C (co oznacza XS, Perl's "Extension System").


65



Wygląda na to, że masz standardowy Cygwin! - Janus Troelsen
json_pp może być używany w taki sam sposób i najprawdopodobniej jest łatwo instalowany w systemie (w Debianie jest w pakiecie "perl"). - MichielB
FYI, w moim systemie Mac OS X 10.9, json_pp jest dostępny automatycznie. - Gregg Williams
Lub pp jest dla "ładnego druku" .. - FliiFe
-t null dałeś mi null: niepoprawna forma... ale wyłączenie go działało wspaniale. Dzięki. - Lucas