Πώς μπορώ να γράψω δεδομένα JSON σε ένα αρχείο;

Έχω δεδομένα JSON αποθηκευμένα στη μεταβλητή data.

Θέλω να τα γράψω σε ένα αρχείο κειμένου για δοκιμές, ώστε να μην χρειάζεται να παίρνω τα δεδομένα από το διακομιστή κάθε φορά.

Επί του παρόντος, δοκιμάζω το εξής:

obj = open('data.txt', 'wb')
obj.write(data)
obj.close

TypeError: must be string or buffer, not dict

Πώς να το διορθώσω αυτό;

Λύση

Ξεχάσατε το πραγματικό μέρος του JSON - το data είναι ένα λεξικό και δεν έχει ακόμη κωδικοποιηθεί σε JSON. Γράψτε το έτσι για μέγιστη συμβατότητα (Python 2 και 3):

import json
with open('data.json', 'w') as f:
    json.dump(data, f)

Σε ένα σύγχρονο σύστημα (δηλ. Python 3 και υποστήριξη UTF-8), μπορείτε να γράψετε ένα πιο όμορφο αρχείο με την εντολή

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
Σχόλια (21)

Για να λάβετε ένα αρχείο με κωδικοποίηση utf8 σε αντίθεση με το αρχείο με κωδικοποίηση ascii στην αποδεκτή απάντηση για την Python 2 χρησιμοποιήστε:

import io, json
with io.open('data.txt', 'w', encoding='utf-8') as f:
  f.write(json.dumps(data, ensure_ascii=False))

Ο κώδικας είναι απλούστερος στην Python 3:

import json
with open('data.txt', 'w') as f:
  json.dump(data, f, ensure_ascii=False)

Στα Windows, το όρισμα encoding='utf-8' στο open εξακολουθεί να είναι απαραίτητο.

Για να αποφύγετε την αποθήκευση ενός κωδικοποιημένου αντιγράφου των δεδομένων στη μνήμη (αποτέλεσμα των dumps) και για να εξάγετε utf8-κωδικοποιημένες συμβολοσειρές bytestrings τόσο στην Python 2 όσο και στην 3, χρησιμοποιήστε:

import json, codecs
with open('data.txt', 'wb') as f:
    json.dump(data, codecs.getwriter('utf-8')(f), ensure_ascii=False)

Η κλήση codecs.getwriter είναι περιττή στην Python 3 αλλά απαραίτητη για την Python 2


Αναγνωσιμότητα και μέγεθος:

Η χρήση του ensure_ascii=False προσφέρει καλύτερη αναγνωσιμότητα και μικρότερο μέγεθος:

>>> json.dumps({'price': '€10'})
'{"price": "\\u20ac10"}'
>>> json.dumps({'price': '€10'}, ensure_ascii=False)
'{"price": "€10"}'

>>> len(json.dumps({'абвгд': 1}))
37
>>> len(json.dumps({'абвгд': 1}, ensure_ascii=False).encode('utf8'))
17

Βελτιώστε περαιτέρω την αναγνωσιμότητα προσθέτοντας τις σημαίες indent=4, sort_keys=True (όπως προτείνεται από τον dinos66) στα ορίσματα των dump ή dumps. Με αυτόν τον τρόπο θα έχετε μια όμορφα στοιχισμένη ταξινομημένη δομή στο αρχείο json με το κόστος ενός ελαφρώς μεγαλύτερου μεγέθους αρχείου.

Σχόλια (18)

Θα απαντούσα με μια μικρή τροποποίηση με τις προαναφερθείσες απαντήσεις και αυτό είναι να γράψετε ένα ωραιοποιημένο αρχείο JSON το οποίο τα ανθρώπινα μάτια μπορούν να διαβάσουν καλύτερα. Για το σκοπό αυτό, περάστε το sort_keys ως True και το indent με 4 κενά και είστε έτοιμοι. Φροντίστε επίσης να διασφαλίσετε ότι οι κωδικοί ascii δεν θα γραφτούν στο JSON αρχείο σας:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
Σχόλια (5)