Bagaimana cara menulis data JSON ke file?

1122

Saya memiliki data JSON yang disimpan dalam variabel data.

Saya ingin menulis ini ke file teks untuk pengujian jadi saya tidak harus mengambil data dari server setiap kali.

Saat ini, saya mencoba ini:

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

Dan saya menerima kesalahan ini:

TypeError: harus berupa string atau buffer, bukan dict

Bagaimana cara memperbaikinya?

pengguna1530318
sumber

Jawaban:

2042

Anda lupa bagian JSON yang sebenarnya - dataadalah kamus dan belum dikodekan JSON. Tulis seperti ini untuk kompatibilitas maksimum (Python 2 dan 3):

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

Pada sistem modern (yaitu dukungan Python 3 dan UTF-8), Anda dapat menulis file yang lebih bagus

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)
phihag
sumber
8
ini mungkin berguna untuk membuat cerita bersambung: stackoverflow.com/questions/4512982/…
jedierikb
12
Apakah maksud Anda json.dump atau json.dumps?
TerminalDilettante
153
@TerminalDilettante json.dumpmenulis ke file atau objek seperti file, sedangkan json.dumpsmengembalikan string.
phihag
24
btw: untuk membaca kembali penggunaan data: dengan terbuka ('data.txt') sebagai infile: d = json.load (infile). Lihat: jawaban ini
klaas
9
@denvar Tidak, jawaban ini disetel dengan halus. Pada Python 3, json.dumpmenulis ke file teks, bukan file biner. Anda akan mendapatkan TypeErrorjika file dibuka bersama wb. Pada versi Python yang lebih lama, keduanya wnand wbberfungsi. Pengkodean eksplisit tidak diperlukan karena output json.dumpASCII-only secara default. Jika Anda dapat memastikan bahwa kode Anda tidak pernah berjalan pada versi Python lama dan Anda dan pawang file JSON dapat dengan benar menangani data non-ASCII, Anda dapat menentukan satu dan mengatur ensure_ascii=False.
phihag
267

Untuk mendapatkan file ber- utf8 sebagai ganti ascii- di- enode dalam jawaban yang diterima untuk Python 2 gunakan:

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

Kode ini lebih sederhana dalam Python 3:

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

Di Windows, encoding='utf-8'argumen untuk openmasih diperlukan.

Untuk menghindari penyimpanan salinan data yang dikodekan dalam memori (hasil dumps) dan untuk output bytest yang dikodekan utf8 di Python 2 dan 3, gunakan:

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

The codecs.getwriterpanggilan berlebihan di Python 3 tetapi diperlukan untuk Python 2


Keterbacaan dan ukuran:

Penggunaan ensure_ascii=Falsememberi keterbacaan yang lebih baik dan ukuran yang lebih kecil:

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

Lebih lanjut meningkatkan keterbacaan dengan menambahkan flag indent=4, sort_keys=True(seperti yang disarankan oleh dinos66 ) ke argumen dumpatau dumps. Dengan cara ini Anda akan mendapatkan struktur diurutkan dengan indentasi baik dalam file json dengan biaya ukuran file yang sedikit lebih besar.

Antony Hatchkins
sumber
5
Itu unicodeberlebihan - hasil dari json.dumpssudah merupakan objek unicode. Perhatikan bahwa ini gagal dalam 3.x, di mana seluruh kekacauan mode file output ini telah dibersihkan, dan json selalu menggunakan string karakter (dan karakter I / O) dan tidak pernah byte.
phihag
4
Dalam 2.x type(json.dumps('a'))adalah <type 'str'>. Bahkan type(json.dumps('a', encoding='utf8'))adalah <type 'str'>.
Antony Hatchkins
4
Ya, dalam 3.x json menggunakan string, namun penyandian default adalah ascii. Anda harus secara eksplisit mengatakannya bahwa Anda ingin utf8bahkan dalam 3.x. Diperbarui jawabannya.
Antony Hatchkins
4
Oh, Anda benar sekali - saya pasti bingung. +1 untuk detailnya.
phihag
1
Jawaban Python 3.x bekerja untuk saya walaupun saya menggunakan 2.7. Jawaban 2.x kembali kesalahan: 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128). Jadi ketika ragu, gunakan jawaban 3.x!
Blairg23
162

Saya akan menjawab dengan sedikit modifikasi dengan jawaban yang disebutkan di atas dan itu adalah untuk menulis file JSON cantik yang mata manusia dapat membaca lebih baik. Untuk ini, sampaikan sort_keyssebagai Truedan indentdengan 4 karakter spasi dan Anda siap melakukannya. Juga pastikan untuk memastikan bahwa kode ascii tidak akan ditulis dalam file JSON Anda:

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
ambodi
sumber
2
masih mendapatkanUnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
stevek
1
@ SirBenBenji Pastikan string yang Anda coba tulis diikuti: str.decode ('utf-8').
ambodi
1
@ SirBenBenji Anda dapat mencoba menggunakan codec juga, seperti dinos66 tentukan di bawah ini
Shiv
Anda juga harus mendeklarasikan penyandian Anda dengan menambahkan # -*- coding: utf-8 -*-setelah shebang
aesede
2
+1 untuk sort_keys dan indent. @ aesede Tidak ada gunanya menambahkan baris ini karena akan membuat kesan bahwa solusi ini bekerja dengan python2 juga yang tidak ( UnicodeEncodeErrordengan data non-ascii). Lihat solusi saya untuk detailnya.
Antony Hatchkins
111

Baca dan tulis file JSON dengan Python 2 + 3; bekerja dengan 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)

Penjelasan parameter json.dump:

  • indent: Gunakan 4 spasi untuk membuat indentasi setiap entri, misalnya saat dikt baru dimulai (jika tidak semua akan berada dalam satu baris),
  • sort_keys: urutkan kunci kamus. Ini berguna jika Anda ingin membandingkan file json dengan alat diff / meletakkannya di bawah kontrol versi.
  • separators: Untuk mencegah Python menambahkan spasi spasi tambahan

Dengan satu paket

Lihatlah paket utilitas saya mpuuntuk paket yang super sederhana dan mudah diingat:

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

File JSON dibuat

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

Ujung file umum

.json

Alternatif

Untuk aplikasi Anda, berikut ini mungkin penting:

  • Dukungan oleh bahasa pemrograman lain
  • Kinerja membaca / menulis
  • Kekompakan (ukuran file)

Lihat juga: Perbandingan format serialisasi data

Jika Anda mencari cara untuk membuat file konfigurasi, Anda mungkin ingin membaca artikel pendek saya File konfigurasi dalam Python

Martin Thoma
sumber
2
Perhatikan bahwa force_asciiflag secara Truedefault. Anda akan memiliki "\u20ac"urutan 6-byte yang tidak dapat dibaca untuk masing-masing dalam file json Anda (dan juga karakter non-ascii lainnya).
Antony Hatchkins
Mengapa Anda gunakan openuntuk membaca tetapi io.openuntuk menulis? Apakah mungkin digunakan io.openuntuk membaca juga? Jika demikian, parameter apa yang harus dilewati?
Micah Zoltu
23

Bagi Anda yang mencoba untuk membuang bahasa Yunani atau bahasa "eksotis" lainnya seperti saya tetapi juga mengalami masalah (kesalahan unicode) dengan karakter aneh seperti simbol perdamaian (\ u262E) atau lainnya yang sering terkandung dalam data yang diformat json seperti Twitter, solusinya bisa seperti berikut (sort_keys jelas opsional):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
dinos66
sumber
1
1 Sementara docs merekomendasikan python3 builtin opendan assotiated io.openlebih codecs.open, dalam hal ini juga merupakan hack bagus mundur-kompatibel. Dalam python2 codecs.openlebih "omnivora" daripada io.open (ini bisa "memakan" str dan unicode, mengonversi jika perlu). Orang dapat mengatakan bahwa codecs.openkekhasan ini mengkompensasi json.dumpskekhasan menghasilkan berbagai jenis objek ( str/ unicode) tergantung pada keberadaan string unicode dalam input.
Antony Hatchkins
10

Saya tidak memiliki reputasi yang cukup untuk menambahkan komentar, jadi saya hanya menulis beberapa temuan saya tentang TypeError yang mengganggu ini di sini:

Pada dasarnya, saya pikir itu bug dalam json.dump()fungsi hanya di Python 2 - Tidak bisa membuang data Python (kamus / daftar) yang mengandung karakter non-ASCII, bahkan Anda membuka file dengan encoding = 'utf-8'parameter. (Yaitu apa pun yang Anda lakukan). Tapi, json.dumps()bekerja pada Python 2 dan 3.

Untuk mengilustrasikan ini, menindaklanjuti jawaban phihag: kode dalam jawabannya istirahat dalam Python 2 dengan pengecualian TypeError: must be unicode, not str, jika databerisi karakter non-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)

Namun itu berfungsi dengan baik di Python 3.

ibic
sumber
Berikan alasan saat Anda mengklaim ada sesuatu yang salah. Gunakan @nickname agar orang tersebut diberi tahu. Anda tidak dapat menulis komentar, tetapi Anda dapat membaca komentar. Seperti yang sudah dinyatakan dalam jawaban saya untuk komentar pertama, coba data = {'asdf': 1}. Anda akan mendapatkan yang terkenal TypeErrordengan varian (kedua) Anda.
Antony Hatchkins
Mengenai ensure_ascii- perlu jika Anda ingin mendapatkan output utf8 "nyata". Tanpanya Anda akan memiliki ascii polos dengan 6 byte per huruf rusia dibandingkan dengan 2 byte per karakter dengan bendera ini.
Antony Hatchkins
@AntonyHatchkins Anda benar untuk unicode()bagian itu. Saya baru sadar untuk iopaket di Python 2, write()perlu unicode, tidak str.
ibic
1
Kode ini berfungsi untuk saya bahkan dengan python2.6.6, Debian (10 Des 2010). Seperti halnya dengan python2.7.9 atau python3. Periksa sekali lagi, silakan.
Antony Hatchkins
7

Tulis data dalam file menggunakan JSON menggunakan json.dump () atau json.dumps () yang digunakan. tulis seperti ini untuk menyimpan data dalam file.

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

contoh ini dalam daftar adalah menyimpan ke file.

Vishal Gediya
sumber
itu mirip tetapi berikan dengan contoh
Vishal Gediya
5

Untuk menulis JSON dengan lekukan, "cetak cantik":

import json

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

Juga, jika Anda perlu men-debug JSON yang diformat dengan tidak benar, dan ingin pesan kesalahan yang bermanfaat, gunakan import simplejsonpustaka, alih-alih import json(fungsinya harus sama)

James Wierzba
sumber
4
json.dump(data, open('data.txt', 'wb'))
Alexander
sumber
2
Ini melakukan hal yang sama dengan jawaban @ phihag, tetapi tidak dijamin berfungsi setiap saat. Pertimbangkan kode tersebut: f = open('1.txt', 'w'); f.write('a'); input(). Jalankan dan kemudian SYGTERM ( Ctrl-Zlalu kill %1di linux, Ctrl-Breakdi Windows). 1.txtakan memiliki 0 byte. Itu karena tulisannya buffered dan file tidak memerah tidak ditutup pada saat SYGTERM terjadi. withblokir menjamin bahwa file selalu ditutup seperti halnya blok 'coba / akhirnya' tetapi lebih pendek.
Antony Hatchkins
3

Menulis JSON ke File

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)

Membaca JSON dari File

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('')
iman
sumber
Selamat datang di Stack Overflow. Jika Anda memutuskan untuk menjawab pertanyaan yang lebih lama yang sudah mapan dan jawaban yang benar, menambahkan jawaban baru di akhir hari mungkin tidak memberi Anda kredit apa pun. Jika Anda memiliki beberapa informasi baru yang berbeda, atau Anda yakin jawaban lain semuanya salah, tentu saja tambahkan jawaban baru, tetapi 'jawaban lain' memberikan informasi dasar yang sama lama setelah pertanyaan diajukan biasanya dimenangkan ' tidak memberi Anda banyak kredit. (Anda menunjukkan beberapa data sampel; itu bagus, tapi saya tidak yakin itu cukup, terutama karena Anda tidak menunjukkan apa yang dihasilkan untuk data sampel.)
Jonathan Leffler
Ok terima kasih untuk bimbingannya
iman
2

jika Anda mencoba untuk menulis bingkai data panda menjadi file menggunakan format json saya akan merekomendasikan ini

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
Franco Miguel Contreras
sumber
2

Semua jawaban sebelumnya benar di sini adalah contoh yang sangat sederhana:

#! /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()

masukkan deskripsi gambar di sini

grepit
sumber
1

Jawaban yang diterima baik-baik saja. Namun, saya mengalami kesalahan "tidak json serializable" menggunakan itu.

Inilah cara saya memperbaikinya dengan open("file-name.json", 'w')sebagai output:

output.write(str(response))

Meskipun ini bukan perbaikan yang baik karena file json yang dibuatnya tidak akan memiliki tanda kutip ganda, namun sangat bagus jika Anda mencari yang cepat dan kotor.

Akshat Bajaj
sumber
0

Data JSON dapat ditulis ke file sebagai berikut

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

Menulis ke file:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
Ashok Kumar Jayaraman
sumber