Jak zapisać dane JSON do pliku?

Mam dane JSON zapisane w zmiennej data.

Chcę zapisać to do pliku tekstowego do testów, więc nie muszę za każdym razem pobierać danych z serwera.

Obecnie próbuję tego:

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

A ja odbieram ten błąd:

TypeError: musi być string lub buffer, a nie dict

Jak to naprawić?
 1247
Author: sentence, 2012-09-06

14 answers

Zapomniałeś, że część JSON - data jest słownikiem i jeszcze nie jest zakodowana w JSON. Napisz to w ten sposób dla maksymalnej kompatybilności (Python 2 i 3):

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

Na nowoczesnym systemie (tj. Obsługa Pythona 3 i UTF-8), możesz napisać ładniejszy plik za pomocą

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
 2232
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-05 15:08:55

Aby uzyskać utf8-zakodowany plik w przeciwieństwie do ascii-kodowane w zaakceptowanej odpowiedzi dla Pythona 2 Użyj:

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

Kod jest prostszy w Pythonie 3:

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

W systemie Windows, argument encoding='utf-8' do open jest nadal konieczny.

Aby uniknąć przechowywania zakodowanej kopii danych w pamięci (wynik dumps) i wyjścia kodowanych utf8 bajtów w Pythonie 2 i 3, Użyj:

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

wywołanie codecs.getwriter jest redundantne w Pythonie 3, ale wymagane dla Pythona 2


Czytelność i rozmiar:

Użycie ensure_ascii=False daje lepszą czytelność i mniejszy rozmiar:

>>> 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

Dalsza poprawa czytelności poprzez dodanie znaczników indent=4, sort_keys=True (zgodnie z sugestią dinos66) do argumentów dump lub dumps. W ten sposób uzyskasz ładnie wciętą posortowaną strukturę w pliku json kosztem nieco większego rozmiaru pliku.

 275
Author: Antony Hatchkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-07 11:45:32

Odpowiem z lekką modyfikacją z wyżej wymienionymi odpowiedziami, a to jest napisanie pięknego pliku JSON, który ludzkie oczy mogą lepiej odczytać. W tym celu podaj sort_keys jako True i indent z 4 znakami spacji i możesz iść. Zadbaj również o to, aby kody ascii nie były zapisywane w Twoim pliku JSON:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
 164
Author: ambodi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-10 10:32:06

Odczyt i zapis plików JSON za pomocą Pythona 2+3; działa z unicode

# -*- coding: utf-8 -*-
import json

# Make it work for Python 2+3 and with Unicode
import io
try:
    to_unicode = unicode
except NameError:
    to_unicode = str

# Define data
data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
        'a string': 'bla',
        'another dict': {'foo': 'bar',
                         'key': 'value',
                         'the answer': 42}}

# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
    str_ = json.dumps(data,
                      indent=4, sort_keys=True,
                      separators=(',', ': '), ensure_ascii=False)
    outfile.write(to_unicode(str_))

# Read JSON file
with open('data.json') as data_file:
    data_loaded = json.load(data_file)

print(data == data_loaded)

Wyjaśnienie parametrów json.dump:

  • indent: Użyj 4 spacji, aby wciąć każdy wpis, np. gdy zostanie uruchomiony nowy dict (w przeciwnym razie wszystkie będą w jednej linii),
  • sort_keys: sortowanie kluczy słowników. Jest to przydatne, jeśli chcesz porównać pliki json z narzędziem diff / umieścić je pod kontrolą wersji.
  • separators: aby zapobiec dodawaniu końca Pythona whitespaces

Z pakietem

Spójrz na mój pakiet narzędziowy mpu dla super prostego i łatwego do zapamiętania:

import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)

Utworzony plik JSON

{
    "a list":[
        1,
        42,
        3.141,
        1337,
        "help",
        "€"
    ],
    "a string":"bla",
    "another dict":{
        "foo":"bar",
        "key":"value",
        "the answer":42
    }
}

Wspólne zakończenia plików

.json

Alternatywy

Dla Twojego zastosowanie, ważne może być:

  • wsparcie dla innych języków programowania
  • wydajność odczytu / zapisu
  • zwartość (Rozmiar pliku)

Zobacz także: porównanie formatów serializacji danych

Jeśli szukasz sposobu na tworzenie plików konfiguracyjnych, możesz przeczytać mój krótki artykuł pliki konfiguracyjne w Pythonie

 118
Author: Martin Thoma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 21:05:55

Dla tych z Was, którzy próbują zrzucić Grecki lub inne "egzotyczne" języki, takie jak ja, ale mają również problemy (błędy unicode) z dziwnymi znakami, takimi jak symbol pokoju (\u262e) lub inne, które są często zawarte w danych sformatowanych w json, takich jak Twitter, rozwiązanie może być następujące (sort_keys jest oczywiście opcjonalne): {]}

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
 24
Author: dinos66,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-10 14:45:29

Zapis JSON do pliku

import json

data = {}
data['people'] = []
data['people'].append({
    'name': 'Scott',
    'website': 'stackabuse.com',
    'from': 'Nebraska'
})
data['people'].append({
    'name': 'Larry',
    'website': 'google.com',
    'from': 'Michigan'
})
data['people'].append({
    'name': 'Tim',
    'website': 'apple.com',
    'from': 'Alabama'
})

with open('data.txt', 'w') as outfile:
    json.dump(data, outfile)

Odczyt JSON z pliku

import json

with open('data.txt') as json_file:
    data = json.load(json_file)
    for p in data['people']:
        print('Name: ' + p['name'])
        print('Website: ' + p['website'])
        print('From: ' + p['from'])
        print('')
 11
Author: iman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-26 08:35:58

Nie mam wystarczającej reputacji, aby dodać w komentarzach, więc po prostu piszę tutaj Niektóre z moich ustaleń tego irytującego typu:

Myślę, że to błąd w funkcji json.dump() w Pythonie 2 tylko - nie może zrzucić danych Pythona (słownik / lista) zawierających znaki inne niż ASCII, nawet otwierasz Plik z parametrem encoding = 'utf-8'. (tj. bez względu na to, co robisz). Ale json.dumps() działa zarówno na Pythonie 2 jak i 3.

Aby to zilustrować, podążając za odpowiedzią phihaga: kod w odpowiedzi łamie się w Pythonie 2 z wyjątkiem TypeError: must be unicode, not str, Jeśli data zawiera znaki spoza ASCII. (Python 2.7.6, Debian):

import json
data = {u'\u0430\u0431\u0432\u0433\u0434': 1} #{u'абвгд': 1}
with open('data.txt', 'w') as outfile:
    json.dump(data, outfile)

Działa jednak dobrze w Pythonie 3.

 10
Author: ibic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 09:07:50

Zapis danych w pliku za pomocą JSON use json.dump () lub json.dumps () używane. napisz w ten sposób, aby zapisać dane w pliku.

import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
    json.dump(data, txtfile)

Ten przykład w liście jest przechowywany w pliku.

 9
Author: Vishal Gediya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-24 10:58:21
json.dump(data, open('data.txt', 'wb'))
 5
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-29 20:16:51

Aby napisać JSON z wcięciem, "ładny Wydruk":

import json

outfile = open('data.json')
json.dump(data, outfile, indent=4)

Ponadto, jeśli chcesz debugować nieprawidłowo sformatowany JSON i potrzebujesz pomocnego Komunikatu o błędzie, użyj biblioteki import simplejson zamiast import json (funkcje powinny być takie same)

 5
Author: James Wierzba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-13 22:38:01

Jeśli próbujesz zapisać ramkę danych pandy do pliku w formacie json, polecam to

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
 2
Author: Franco Miguel Contreras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-03 07:48:30

Wszystkie poprzednie odpowiedzi są poprawne oto bardzo prosty przykład:

#! /usr/bin/env python
import json

def write_json():
    # create a dictionary  
    student_data = {"students":[]}
    #create a list
    data_holder = student_data["students"]
    # just a counter
    counter = 0
    #loop through if you have multiple items..         
    while counter < 3:
        data_holder.append({'id':counter})
        data_holder.append({'room':counter})
        counter += 1    
    #write the file        
    file_path='/tmp/student_data.json'
    with open(file_path, 'w') as outfile:
        print("writing file to: ",file_path)
        # HERE IS WHERE THE MAGIC HAPPENS 
        json.dump(student_data, outfile)
    outfile.close()     
    print("done")

write_json()

Tutaj wpisz opis obrazka

 2
Author: grepit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-10 05:53:55

Zaakceptowana odpowiedź jest w porządku. Jednak napotkałem błąd" is not JSON serializable " używając tego.

Oto Jak to naprawiłem z open("file-name.json", 'w') jako wyjściem:

output.write(str(response))

Chociaż nie jest to dobra poprawka, ponieważ utworzony plik json nie będzie miał podwójnych cudzysłowów, jednak jest to świetne, jeśli szukasz szybkich i brudnych.

 1
Author: Akshat Bajaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-04 22:10:20

Dane JSON można zapisać do pliku w następujący sposób

hist1 = [{'val_loss': [0.5139984398465246],
'val_acc': [0.8002029867684085],
'loss': [0.593220705309384],
'acc': [0.7687131817929321]},
{'val_loss': [0.46456472964199463],
'val_acc': [0.8173602046780344],
'loss': [0.4932038113037539],
'acc': [0.8063946213802453]}]

Zapis do pliku:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
 0
Author: Ashok Kumar Jayaraman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-01 12:00:47