Branje in pisanje JSON v datoteko v Pythonu

Predstavitev

V tem priročniku si bomo ogledali, kako brati in pisati podatke JSON iz in v datoteko v Pythonu z uporabo json modul.

JSON (JavaScript Object Notation) je izjemno priljubljena oblika za serializacijo podatkov, glede na to, kako splošno uporabna in lahka je – hkrati pa je dokaj prijazna do ljudi. Predvsem se obširno uporablja v svetu spletnega razvoja, kjer boste verjetno naleteli na serializirane predmete JSON, poslane iz API-ji REST, konfiguracijo aplikacije ali celo preprosto shranjevanje podatkov.

Glede na njegovo razširjenost je branje in razčlenjevanje datotek JSON (ali nizov) precej običajno, pisanje JSON za pošiljanje pa je enako pogosto. V tem priročniku si bomo ogledali, kako izkoristiti json modul za branje in pisanje JSON v Python.

Pisanje JSON v datoteko s Pythonom z json.dump() in json.dumps()

Za pisanje vsebine JSON v datoteko v Pythonu – lahko uporabimo json.dump() in json.dumps(). To so ločene metode in dosegli drugačen rezultat:

  • json.dumps() – Serializira predmet v obliko JSON niz
  • json.dump() – Serializiran predmet v tok JSON za shranjevanje v datoteke ali vtičnice

Opomba: "S" v "dumps" je pravzaprav okrajšava za "niz izpisa".

Naravni format JSON je podoben a map v informatiki – zemljevid key-value parov. V Pythonu je a Slovar je implementacija zemljevida, tako da bomo seveda lahko zvesto predstavili JSON prek a dict. Slovar lahko vsebuje druge ugnezdene slovarje, nize, logične vrednosti ali druge primitivne vrste, kot so cela števila in nizi.

(Greš.

Opomba: Vgrajeno json paket ponuja več priročnih metod, ki nam omogočajo pretvorbo med JSON in slovarji.

(Greš.

Kot rečeno, uvozimo json modul, definirajte slovar z nekaterimi podatki in ga nato pretvorite v JSON, preden shranite v datoteko:

import json

data = {
    'employees' : [
        {
            'name' : 'John Doe',
            'department' : 'Marketing',
            'place' : 'Remote'
        },
        {
            'name' : 'Jane Doe',
            'department' : 'Software Engineering',
            'place' : 'Remote'
        },
        {
            'name' : 'Don Joe',
            'department' : 'Software Engineering',
            'place' : 'Office'
        }
    ]
}


json_string = json.dumps(data)
print(json_string)

Rezultat tega je:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Tukaj imamo preprost slovar z nekaj employees, od katerih ima vsaka name, department in place. dumps() funkcija json modul odlagališča slovar v vsebino JSON in vrne a JSON niz.

Ko je serializiran, se lahko odločite, da ga pošljete drugi storitvi, ki ga bo deserializirala ali, recimo, shranila. Za shranjevanje tega niza JSON v datoteko preprosto odpremo datoteko v načinu pisanja in jo zapišemo. Če podatkov ne želite izvleči v neodvisno spremenljivko za kasnejšo uporabo in bi jih radi samo odložili v datoteko, lahko preskočite dumps() funkcijo in uporabo dump() instad:


with open('json_data.json', 'w') as outfile:
    outfile.write(json_string)


with open('json_data.json', 'w') as outfile:
    json.dump(json_string, outfile)

Vsak predmet, podoben datoteki, je mogoče posredovati drugemu argumentu dump() funkcijo, tudi če ni dejanska datoteka. Dober primer tega bi bila vtičnica, ki jo je mogoče odpreti, zapreti in vanjo pisati podobno kot v datoteko.

Branje JSON iz datoteke s Pythonom z json.load() in json.loads()

Preslikava med vsebino slovarja in nizom JSON je preprosta, zato je pretvorba med njima enostavna. Ista logika kot pri dump() in dumps() se nanaša na load() in loads(). Podobno kot json.dumps()je json.loads() funkcija sprejme niz JSON in ga pretvori v slovar, medtem ko json.load() omogoča nalaganje v datoteko:

import json

with open('json_data.json') as json_file:
    data = json.load(json_file)
    print(data)

Rezultat tega je:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Druga možnost je, da preberemo niz JSON v slovar:

import json

python_dictionary = json.loads(json_string)
print(python_dictionary)

Kar ima tudi za posledico:

{'employees': [{'name': 'John Doe', 'department': 'Marketing', 'place': 'Remote'}, {'name': 'Jane Doe', 'department': 'Software Engineering', 'place': 'Remote'}, {'name': 'Don Joe', 'department': 'Software Engineering', 'place': 'Office'}]}

Ta je še posebej uporaben za razčlenjevanje odgovorov REST API, ki pošiljajo JSON. Ti podatki pridejo do vas kot niz, ki ga lahko nato posredujete json.loads() neposredno in imate veliko bolj obvladljiv slovar za delo!

Razvrščanje, lepo tiskanje, ločila in kodiranje

Pri serializaciji vaših podatkov v JSON s Pythonom standardna oblika, katere namen je zmanjšati potreben pomnilnik za prenos sporočil, ni zelo berljiva, ker so odstranjeni presledki. Čeprav je to idealno vedenje za prenos podatkov (računalnikom ni pomembna berljivost, marveč velikost) – včasih boste morda morali narediti majhne spremembe, na primer dodati presledke, da bodo berljivi.

Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!

Opomba: json.dump()/json.dumps() in json.load()/json.loads() vse ponujajo nekaj možnosti oblikovanja.

Pretty-Printing JSON v Pythonu

Narediti JSON človeku berljivega (aka "lep tisk") je tako enostavno kot posredovanje celoštevilske vrednosti za indent parameter:

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, indent=4))

S tem se na vsakem novem logičnem bloku prepogne zamik s 4 presledki:

{
    "people": [
        {
            "website": "stackabuse.com", 
            "from": "Nebraska", 
            "name": "Scott"
        }
    ]
}

Druga možnost je uporaba orodja ukazne vrstice – json.tool. Z njim lahko lepo natisnete JSON v ukazni vrstici, ne da bi to vplivalo na poslani niz in samo vplivalo na to, kako je prikazan v standardni izhodni cevi:

$ echo '{"people":[{"name":"Scott", "website":"stackabuse.com", "from":"Nebraska"}]}' | python -m json.tool
{
    "people": [
        {
            "name": "Scott",
            "website": "stackabuse.com"
            "from": "Nebraska",
        }
    ]
}

Razvrščanje objektov JSON po ključih

V smislu JSON:

"Predmet je neurejen niz parov ime/vrednost."

Vrstni red ključev ni zajamčen, vendar je možno, da boste morda morali uveljaviti vrstni red ključev. Če želite doseči naročanje, lahko prenesete True k sort_keys možnost pri uporabi json.dump() or json.dumps():

import json
data = {'people':[{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
print(json.dumps(data, sort_keys=True, indent=4))

Rezultat tega je:

{
    "people": [
        {
            "from": "Nebraska",
            "name": "Scott",
            "website": "stackabuse.com"
        }
    ]
}

ASCII besedilo in kodiranje

Privzeto, json.dump() in json.dumps() bo zagotovil, da bo besedilo v danem slovarju Python kodirano ASCII. Če so prisotni znaki, ki niso ASCII, so samodejno ubežni, kot je prikazano v naslednjem primeru:

import json
data = {'item': 'Beer', 'cost':'£4.00'}
jstr = json.dumps(data, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "u00a34.00"
}

To ni vedno sprejemljivo in v mnogih primerih boste morda želeli ohraniti znake Unicode nespremenjene. Če želite to narediti, nastavite ensure_ascii možnost, da False:

jstr = json.dumps(data, ensure_ascii=False, indent=4)
print(jstr)
{
    "item": "Beer",
    "cost": "£4.00"
}

Preskoči tipe podatkov ključev po meri

Če je ključ v vašem slovarju neprimitivnega tipa (str, int, float, bool or None) Od TypeError se pojavi, ko poskušate vsebino JSON prenesti v datoteko. Te tipke lahko preskočite prek skipkeys argument:

jstr = json.dumps(data, skipkeys=True)

Omogočanje in onemogočanje krožnega preverjanja

Če se lastnost predmeta JSON sklicuje nase ali na drug objekt, ki se sklicuje nazaj na nadrejeni objekt, se ustvari neskončno rekurziven JSON. Neskončna rekurzija običajno povzroči hitro dodeljevanje pomnilnika, dokler napravi ne zmanjka pomnilnika, v primeru izpisa JSON pa RecursionError se dvigne in odlaganje se ustavi.

To je urejeno z check_circular zastavo, ki je True privzeto in preprečuje morebitne težave pri pisanju krožnih odvisnosti. Če ga želite izklopiti, ga lahko nastavite na »False«:

jstr = json.dumps(data, check_circular=False)

Vendar upoštevajte, da je to zelo ni priporočljivo.

Omogočanje in onemogočanje NaN

NaN-vrednosti, kot npr -inf, inf in nan se lahko prikrade v predmete, ki jih želite serializirati ali deserializirati. standard JSON ne dovoli za vrednosti NaN, vendar še vedno nosijo logično vrednost, ki bi jo morda želeli prenesti v sporočilu. Po drugi strani pa boste morda želeli uveljaviti te vrednosti NaN ne prenese in namesto tega povzroči izjemo. The allow_nan zastavica je nastavljena na True privzeto in vam omogoča serializacijo in deserializacijo vrednosti NaN, ki jih nadomestite z ekvivalenti JavaScript (Inifinity, -Infinity in NaN).

Če zastavico nastavite na False namesto tega boste preklopili na strogo standardizirano obliko zapisa JSON, ki dvigne a ValueError če vaši objekti vsebujejo atribute s temi vrednostmi:

jstr = json.dumps(data, allow_nan=False)

Spreminjanje ločil

V JSON so ključi ločeni od vrednosti z dvopičji (:), postavke pa so med seboj ločene z vejicami (,):

key1:value1,
key2:value2

Privzeta ločila za branje in pisanje JSON v Pythonu so (', ', ': ') z beli prostori za vejicami in dvopičji. Te lahko spremenite tako, da preskočite presledke in tako naredite JSON nekoliko bolj kompakten, ali popolnoma spremenite ločila z drugimi posebnimi znaki za drugačno predstavitev:


jstr = json.dumps(data, separators=(',', ':'))

Težave z združljivostjo s Pythonom 2

Če uporabljate starejšo različico Pythona (2.x) – lahko naletite na a TypeError med poskusom izpisa vsebine JSON v datoteko. Namreč, če vsebina vsebuje znak, ki ni ASCII, a TypeError je dvignjen, čeprav posredujete argument kodiranja, ko uporabljate json.dump() metoda:


with open('json_data.json', 'w', encoding='utf-8') as outfile:
    json.dump(json_string, outfile, ensure_ascii=False)

Če naletite na ta robni primer, ki je bil od takrat popravljen v naslednjih različicah Pythona – poskusite uporabiti json.dumps() namesto tega in zapišite vsebino niza v datoteko namesto pretakanja vsebine neposredno v datoteko.

zaključek

V tem priročniku smo vam predstavili json.dump(), json.dumps(), json.load()in json.loads() metode, ki pomagajo pri serializaciji in deserializaciji nizov JSON.

Nato smo si ogledali, kako lahko razvrstite predmete JSON, jih lepo natisnete, spremenite kodiranje, preskočite tipe ključnih podatkov po meri, omogočite ali onemogočite krožna preverjanja in ali so NaN dovoljeni, pa tudi, kako spremeniti ločila za serializacija in deserializacija.

Glede na to, da je JSON eden najbolj priljubljenih načinov serializacije strukturiranih podatkov, boste verjetno morali z njim precej pogosto komunicirati, zlasti pri delu s spletnimi aplikacijami. Pythonov json modul je odličen način za začetek, čeprav boste to verjetno našli simplejson je še ena odlična alternativa, ki je veliko manj stroga glede sintakse JSON.

Časovni žig:

Več od Stackabuse