JSON lezen en schrijven naar een bestand in Python

Introductie

In deze handleiding bekijken we hoe JSON-gegevens van en naar een bestand in Python kunnen worden gelezen en geschreven met behulp van de json module.

JSON (JavaScript-objectnotatie) is een extreem populair formaat voor dataserialisatie, gezien hoe algemeen toepasbaar en lichtgewicht het is - terwijl het ook redelijk mensvriendelijk is. Het wordt met name op grote schaal gebruikt in de wereld van webontwikkeling, waar u waarschijnlijk JSON-geserialiseerde objecten zult tegenkomen die worden verzonden vanuit REST API's, applicatieconfiguratie of zelfs eenvoudige gegevensopslag.

Gezien de prevalentie is het lezen en parseren van JSON-bestanden (of tekenreeksen) vrij gebruikelijk, en het schrijven van JSON om te worden verzonden is net zo gebruikelijk. In deze gids zullen we bekijken hoe u gebruik kunt maken van de json module om JSON in Python te lezen en te schrijven.

JSON naar een bestand schrijven met Python met json.dump() en json.dumps()

Om JSON-inhoud naar een bestand in Python te schrijven โ€“ kunnen we gebruiken json.dump() en json.dumps(). Dit zijn afzonderlijke methodes en bereik een ander resultaat:

  • json.dumps() - Serialiseert een object in een JSON-indeling snaar
  • json.dump() - Een object geserialiseerd in een JSON-stream om op te slaan in bestanden of sockets

Opmerking: De "s" in "dumps" is eigenlijk een afkorting voor "dump-tekenreeks".

Het natuurlijke formaat van JSON is vergelijkbaar met een kaart in de informatica - een kaart van key-value paren. In Python, een woordenboek is een kaartimplementatie, dus we kunnen JSON natuurlijk getrouw weergeven via een dict. Een woordenboek kan andere geneste woordenboeken, arrays, booleans of andere primitieve typen zoals gehele getallen en tekenreeksen bevatten.

:::

Opmerking: De ingebouwde json pakket biedt verschillende gemaksmethoden waarmee we kunnen converteren tussen JSON en woordenboeken.

:::

Dat gezegd hebbende, laten we de json module, definieer een woordenboek met wat gegevens en converteer het vervolgens naar JSON voordat u het in een bestand opslaat:

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)

Dit resulteert in:

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

Hier hebben we een eenvoudig woordenboek met een paar employees, die elk een hebben name, department en place. De dumps() functie van de json module stortplaatsen een woordenboek in JSON-inhoud en retourneert een JSON-tekenreeks.

Eenmaal geserialiseerd, kunt u besluiten om het naar een andere service te sturen die het zal deserialiseren, of bijvoorbeeld opslaan. Om deze JSON-string in een bestand op te slaan, openen we gewoon een bestand in de schrijfmodus en schrijven we het op. Als u de gegevens niet wilt extraheren in een onafhankelijke variabele voor later gebruik en deze gewoon in een bestand wilt dumpen, kunt u de dumps() functie en gebruik 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)

Elk bestandsachtig object kan worden doorgegeven aan het tweede argument van het dump() functie, zelfs als het geen echt bestand is. Een goed voorbeeld hiervan is een socket, die net als een bestand kan worden geopend, gesloten en beschreven.

JSON uit een bestand lezen met Python met json.load() en json.loads()

De toewijzing tussen woordenboekinhoud en een JSON-tekenreeks is eenvoudig, dus het is gemakkelijk om tussen de twee te converteren. Dezelfde logica als bij dump() en dumps() wordt toegepast op load() en loads(). Net als json.dumps() json.loads() functie accepteert een JSON-tekenreeks en converteert deze naar een woordenboek, terwijl json.load() laat je in een bestand laden:

import json

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

Dit resulteert in:

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

Als alternatief kunnen we een JSON-string in een woordenboek lezen:

import json

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

Wat ook resulteert in:

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

Deze is vooral handig voor het parseren van REST API-antwoorden die JSON verzenden. Deze gegevens komen naar u toe als een string, die u vervolgens kunt doorgeven json.loads() direct, en je hebt een veel overzichtelijker woordenboek om mee te werken!

Sorteren, Pretty-Printing, scheidingstekens en codering

Bij het serialiseren van uw gegevens naar JSON met Python, is het standaardformaat dat gericht is op het minimaliseren van het vereiste geheugen om berichten te verzenden, niet erg leesbaar omdat witruimten worden geรซlimineerd. Hoewel dit het ideale gedrag is voor gegevensoverdracht (computers geven niet om leesbaarheid, maar wel om grootte), moet u soms kleine wijzigingen aanbrengen, zoals het toevoegen van witruimte om het voor mensen leesbaar te maken.

Bekijk onze praktische, praktische gids voor het leren van Git, met best-practices, door de industrie geaccepteerde normen en bijgevoegd spiekbriefje. Stop met Googlen op Git-commando's en eigenlijk leren het!

Opmerking: json.dump()/json.dumps() en json.load()/json.loads() ze bieden allemaal een paar opmaakopties.

Pretty-Printing JSON in Python

JSON leesbaar maken voor mensen (aka "mooi afdrukken") is net zo eenvoudig als het doorgeven van een geheel getal voor de indent parameter:

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

Dit zorgt voor een inspringing van 4 spaties op elk nieuw logisch blok:

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

Een andere optie is om de opdrachtregeltool te gebruiken - json.tool. Hiermee kun je de JSON mooi afdrukken in de opdrachtregel zonder de verzonden tekenreeks te beรฏnvloeden, en alleen van invloed op hoe deze wordt weergegeven op de standaard uitvoerpijp:

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

JSON-objecten sorteren op sleutels

In JSON-termen:

"Een object is een ongeordende set van naam/waarde-paren."

De sleutelvolgorde is niet gegarandeerd, maar het is mogelijk dat u de sleutelvolgorde moet afdwingen. Om ordening te bereiken, kunt u slagen True aan de sort_keys optie bij gebruik 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))

Dit resulteert in:

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

ASCII-tekst en codering

Standaard json.dump() en json.dumps() zal ervoor zorgen dat de tekst in het opgegeven Python-woordenboek ASCII-gecodeerd is. Als er niet-ASCII-tekens aanwezig zijn, worden deze automatisch voorzien van een escape-teken, zoals wordt weergegeven in het volgende voorbeeld:

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

Dit is niet altijd acceptabel en in veel gevallen wilt u misschien uw Unicode-tekens ongewijzigd laten. Stel hiervoor de ensure_ascii optie om False:

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

Sla aangepaste sleutelgegevenstypen over

Als een sleutel in uw woordenboek van een niet-primitief type is (str, int, float, bool or None), The TypeError wordt gegenereerd wanneer u JSON-inhoud in een bestand probeert te dumpen. U kunt deze toetsen overslaan via de skipkeys argument:

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

Circulaire controle in- en uitschakelen

Als een eigenschap van een JSON-object naar zichzelf verwijst, of een ander object dat naar het bovenliggende object verwijst, wordt een oneindig recursieve JSON gemaakt. Oneindige recursie resulteert meestal in snel toegewezen geheugen totdat een apparaat geen geheugen meer heeft, en in het geval van het dumpen van JSON, een RecursionError wordt verhoogd en het storten wordt gestopt.

Dit wordt geregeld door de check_circular vlag, dat is True standaard en voorkomt mogelijke problemen bij het schrijven van circulaire afhankelijkheden. Om het uit te schakelen, kunt u het instellen op `False:

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

Houd er echter rekening mee dat dit is zeer niet aangeraden.

NaNs in- en uitschakelen

NaN-waarden, zoals -inf, inf en nan kunnen objecten binnensluipen die u wilt serialiseren of deserialiseren. JSON-standaard staat niet toe voor NaN-waarden, maar ze hebben nog steeds een logische waarde die u misschien in een bericht wilt verzenden. Aan de andere kant - misschien wilt u die NaN-waarden afdwingen niet verzonden, en in plaats daarvan een uitzondering genereren. De allow_nan vlag is ingesteld op True standaard, en stelt u in staat om NaN-waarden te serialiseren en te deserialiseren, en ze te vervangen door de JavaScript-equivalenten (Inifinity, -Infinity en NaN).

Als u de vlag op False in plaats daarvan schakel je over naar een strikt JSON-gestandaardiseerd formaat, wat een ValueError als uw objecten attributen bevatten met deze waarden:

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

Wisselende scheidingstekens

In JSON worden de sleutels gescheiden van waarden met dubbele punten (:) en de items worden van elkaar gescheiden met komma's (,):

key1:value1,
key2:value2

De standaard scheidingstekens voor het lezen en schrijven van JSON in Python is (', ', ': ') Met witruimtes achter de komma's en dubbele punten. U kunt deze wijzigen om de witruimten over te slaan en zo de JSON een beetje compacter te maken, of de scheidingstekens volledig wijzigen met andere speciale tekens voor een andere weergave:


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

Compatibiliteitsproblemen met Python 2

Als u een oudere versie van Python (2.x) gebruikt, kunt u een TypeError tijdens het proberen JSON-inhoud in een bestand te dumpen. Namelijk, als de inhoud een niet-ASCII-teken bevat, a TypeError wordt verhoogd, zelfs indien u geeft het coderingsargument door wanneer u de json.dump() methode:


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

Als je deze edge-case tegenkomt, die sindsdien is opgelost in volgende Python-versies, probeer dan te gebruiken json.dumps() in plaats daarvan en schrijf de inhoud van de tekenreeks in een bestand in plaats van de inhoud rechtstreeks in een bestand te streamen.

Conclusie

In deze gids hebben we u kennis laten maken met de json.dump(), json.dumps(), json.load() en json.loads() methoden, die helpen bij het serialiseren en deserialiseren van JSON-strings.

Vervolgens hebben we gekeken hoe u JSON-objecten kunt sorteren, ze mooi kunt afdrukken, de codering kunt wijzigen, aangepaste sleutelgegevenstypen kunt overslaan, circulaire controles kunt in- of uitschakelen en of NaN's zijn toegestaan, en hoe u de scheidingstekens voor serialisatie en deserialisatie.

Omdat JSON een van de meest populaire manieren is om gestructureerde gegevens te serialiseren, zult u er waarschijnlijk vrij vaak mee moeten communiceren, vooral wanneer u aan webapplicaties werkt. Pythons json module is een geweldige manier om aan de slag te gaan, hoewel je dat waarschijnlijk zult vinden eenvoudige json is een ander geweldig alternatief dat veel minder streng is voor de JSON-syntaxis.

Tijdstempel:

Meer van Stapelmisbruik