Json.dump ikke med ‘skal unicode, ikke str’ TypeError

Jeg har en json fil, som tilfældigvis har et væld af Kinesisk og Japansk (og andre sprog) tegn. Jeg lægger det ind på min python 2.7 script ved hjælp af io.open som følger:

with io.open('multiIdName.json', encoding="utf-8") as json_data:
    cards = json.load(json_data)

Jeg føjer en ny ejendom til at json, alle gode. Så jeg forsøger at skrive den ud til en anden fil:

with io.open("testJson.json",'w',encoding="utf-8") as outfile:
        json.dump(cards, outfile, ensure_ascii=False)

Det er, når jeg får fejlen TypeError: must be unicode, not str

Jeg prøvede at skrive outfile som en binær (with io.open("testJson.json",'wb') as outfile:), men jeg ender op med ting denne:

{"multiverseid": 262906, "name": "\u00e6\u00b8\u00b8\u00e9\u009a\u00bc\u00e7\u008b\u00ae\u00e9\u00b9\u00ab", "language": "Chinese Simplified"}

Jeg troede åbning og skriver det i den samme kodning, der ville være nok, samt ensure_ascii flag, men det er klart ikke. Jeg ønsker blot at bevare de tegn, som fandtes i den fil, før jeg kører mit script, uden dem bliver til \u s.

Jeg er ikke sikker. Jeg tror, det er fordi du er ved at åbne filen-pointer som en utf-8 kodet fil, men du dumpe en string type objekt (cards).
Ah, bør har nævnt, kort er et json objekt: cards = json.load(json_data)
hvad er den nye ejendom, som du føjer? er det muligt at skrive en Minimal Kontrollerbare Eksempel?

OriginalForfatteren IronWaffleMan | 2016-03-15

3 svar

  1. 29

    Kan du prøve følgende?

    with io.open("testJson.json",'w',encoding="utf-8") as outfile:
      outfile.write(unicode(json.dumps(cards, ensure_ascii=False)))
    Der synes at have gjort det trick, tak. Jeg formoder, at den outfile.skriv tager output fra json.lossepladser og derefter skriver til filen?
    Dejligt 🙂 Ja. den outfile.skriv(indhold) – skriver indholdet til outfile. Mens outfile refererer til “testJson.json” fil. se mere på docs.python.org/2/tutorial/inputoutput.html
    Fare! Du har fået en stiltiende str->Unicode konvertering, uden at en kodning, der er defineret. I Python 2.x, standard kodning er ASCII, så vil du få en UnicodeDecodeError undtagelse, hvis din JSON indeholder ikke-ASCII-tegn
    Dette er faktisk stadig ikke korrekte :/
    Du kan have 8-bit strenge givet til json, og så vil resultatet stadig pause.

    OriginalForfatteren Yaron

  2. 4

    Årsagen til denne fejl er den helt dum adfærd json.dumps i Python 2:

    >>> json.dumps({'a': 'a'}, ensure_ascii=False)
    '{"a": "a"}'
    >>> json.dumps({'a': u'a'}, ensure_ascii=False)
    u'{"a": "a"}'
    >>> json.dumps({'a': 'ä'}, ensure_ascii=False)
    '{"a": "\xc3\xa4"}'
    >>> json.dumps({u'a': 'ä'}, ensure_ascii=False)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
        sort_keys=sort_keys, **kw).encode(obj)
      File "/usr/lib/python2.7/json/encoder.py", line 210, in encode
        return ''.join(chunks)
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

    Dette kombineret med det faktum, at io.open med encoding sæt kun accepterer unicode objekter (som i sig selv er ret), fører til problemer.

    Returtype er helt afhængig af, hvad der er den type af nøgler og værdier i ordbogen, hvis ensure_ascii=False, men str returneres altid, hvis ensure_ascii=True. Hvis du kan ved et uheld sat 8-bit-strenge til ordbøger, du kan ikke blindt at konvertere denne type vende tilbage til unicode, fordi du skal at indstille den kodning, formentlig UTF-8:

    >>> x = json.dumps(obj, ensure_ascii=False)
    >>> if isinstance(x, str):
    ...     x = unicode(x, 'UTF-8')

    I dette tilfælde, jeg mener, du kan bruge json.dump til at skrive til en åben binær fil, men hvis du har brug for at gøre noget mere kompliceret med de deraf følgende objekt, har du sandsynligvis brug for ovenstående kode.


    En løsning er at afslutte alle denne kodning/dekodning vanvid ved at skifte til Python 3.

    Jeg tror dit svar bedre svar på spørgsmålet. Vil du tilføje skrive en del at dit svar, og jeg vil slette mine svar?
    naah travlt nu, og jeg ramte repcap i dag allerede 😀
    Hvis jeg formået at konvertere mit script til at py3, hvordan ville kodning håndtering af forandring?

    OriginalForfatteren Antti Haapala

  3. 3

    JSON-modul håndterer kodning og afkodning for dig, så kan du blot åbne input og output-filer i binær tilstand. JSON-modul forudsætter, at UTF-8-kodning, men kan ændres ved hjælp af encoding attribut på load() og dump() metoder.

    with open('multiIdName.json', 'rb') as json_data:
        cards = json.load(json_data)

    derefter:

    with open("testJson.json", 'wb') as outfile:
        json.dump(cards, outfile, ensure_ascii=False)


    Tak til @Antti Haapala, Python-2.x JSON-modul giver enten Unicode eller str, afhængigt af indholdet af objektet.

    Du bliver nødt til at tilføje en følelse ind for at sikre resultatet er en Unicode, før skrivning gennem io:

    with io.open("testJson.json", 'w', encoding="utf-8") as outfile:
        my_json_str = json.dumps(my_obj, ensure_ascii=False)
        if isinstance(my_json_str, str):
            my_json_str = my_json_str.decode("utf-8")
    
        outfile.write(my_json_str)
    Når jeg, at jeg får: UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
    Fra hvilken linje?
    Er du sikker på du indstille b tilstand på både open() opkald?
    Jep, jeg er sikker. Det var på json.dump linje.

    OriginalForfatteren Alastair McCormack

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *