ฉันจะเขียนข้อมูล JSON ไปยังไฟล์ได้อย่างไร


1122

ฉันมี JSON dataข้อมูลเก็บไว้ในตัวแปร

ฉันต้องการเขียนสิ่งนี้ลงในไฟล์ข้อความเพื่อทำการทดสอบดังนั้นฉันไม่จำเป็นต้องหยิบข้อมูลจากเซิร์ฟเวอร์ในแต่ละครั้ง

ขณะนี้ฉันลองทำสิ่งนี้:

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

และฉันได้รับข้อผิดพลาดนี้:

TypeError: ต้องเป็นสตริงหรือบัฟเฟอร์ไม่ใช่ dict

จะแก้ไขได้อย่างไร?

คำตอบ:


2040

คุณลืมส่วน JSON จริง - dataเป็นพจนานุกรมและยังไม่ได้เข้ารหัส JSON เขียนแบบนี้เพื่อความเข้ากันได้สูงสุด (Python 2 และ 3):

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

ในระบบที่ทันสมัย ​​(เช่นการสนับสนุน Python 3 และ UTF-8) คุณสามารถเขียนไฟล์ nicer ด้วย

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

8
สิ่งนี้อาจมีประโยชน์สำหรับการทำให้เป็นอันดับ: stackoverflow.com/questions/4512982/…
jedierikb

12
คุณหมายถึง json.dump หรือ json.dumps?
TerminalDilettante

153
@TerminalDilettante json.dumpเขียนไปยังไฟล์หรือวัตถุเหมือนไฟล์ในขณะที่json.dumpsส่งกลับสตริง
Phihag

24
btw: เพื่ออ่านการใช้ข้อมูลอีกครั้ง: ด้วย open ('data.txt') เป็น infile: d = json.load (infile) ดู: คำตอบนี้
klaas

9
@denvar ไม่คำตอบนี้ได้รับการปรับแต่งอย่างประณีต บน Python 3 json.dumpเขียนไปยังไฟล์ข้อความไม่ใช่ไฟล์ไบนารี คุณจะได้รับถ้าแฟ้มถูกเปิดด้วยTypeError wbเมื่อวันที่รุ่นเก่าหลามทั้งwNAND wbทำงาน การเข้ารหัสที่ชัดเจนไม่จำเป็นเนื่องจากการส่งออกjson.dumpเป็น ASCII เท่านั้นโดยค่าเริ่มต้น หากคุณมั่นใจได้ว่ารหัสของคุณไม่เคยทำงานในเวอร์ชัน Python ดั้งเดิมและคุณและตัวจัดการของไฟล์ JSON สามารถจัดการข้อมูลที่ไม่ใช่ ASCII ได้อย่างถูกต้องคุณสามารถระบุหนึ่งชุดและตั้งค่าensure_ascii=Falseได้
Phihag

267

ในการรับไฟล์utf8 -encodedเมื่อเทียบกับascii -encodedในคำตอบที่ยอมรับสำหรับ 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-encodedทั้งใน 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 โดยมีขนาดไฟล์ใหญ่ขึ้นเล็กน้อย


5
unicodeเป็นฟุ่มเฟือย - ผลมาจากการjson.dumpsที่มีอยู่แล้ววัตถุ Unicode โปรดทราบว่าสิ่งนี้ล้มเหลวใน 3.x ซึ่งระเบียบทั้งหมดของโหมดไฟล์เอาต์พุตได้รับการทำความสะอาดแล้วและ json ใช้สตริงอักขระ (และอักขระ I / O) เสมอและไม่มีไบต์
Phihag

4
ใน 2.x คือtype(json.dumps('a')) <type 'str'>แม้จะเป็นtype(json.dumps('a', encoding='utf8')) <type 'str'>
Antony Hatchkins

4
ใช่ใน 3.x json ใช้สตริง แต่การเข้ารหัสเริ่มต้นคือ ascii คุณต้องบอกอย่างชัดเจนว่าคุณต้องการutf8แม้ใน 3.x อัปเดตคำตอบ
Antony Hatchkins

4
โอ้คุณพูดถูกต้อง - ฉันต้องสับสนอะไรซักอย่าง +1 สำหรับรายละเอียด
Phihag

1
คำตอบ Python 3.x ใช้งานได้สำหรับฉันแม้ว่าฉันจะใช้ 2.7 คำตอบ 2.x 'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128)กลับข้อผิดพลาด: ดังนั้นเมื่อสงสัยให้ใช้คำตอบ 3.x!
Blairg23

162

ฉันจะตอบด้วยการปรับเปลี่ยนเล็กน้อยกับคำตอบข้างต้นและนั่นคือการเขียนไฟล์ JSON prettified ซึ่งสายตามนุษย์สามารถอ่านได้ดีขึ้น สำหรับเรื่องนี้ผ่าน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)

2
ยังคงได้รับUnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
สตีฟ

1
@SirBenBenji ตรวจสอบให้แน่ใจว่าสตริงที่คุณพยายามจะเขียนมีดังนี้: str.decode ('utf-8')
ambodi

1
@SirBenBenji คุณสามารถลองใช้ตัวแปลงสัญญาณได้เช่นกันเนื่องจาก dinos66 ระบุไว้ด้านล่าง
Shiv

คุณต้องประกาศการเข้ารหัสของคุณโดยเพิ่ม# -*- coding: utf-8 -*-หลังจาก shebang
aesede

2
+1 สำหรับ sort_keys และเยื้อง @aesede มันไม่ดีที่จะเพิ่มบรรทัดนี้เพราะมันจะสร้างความประทับใจว่าโซลูชันนี้ทำงานร่วมกับ python2 เช่นกันซึ่งไม่เป็นเช่นนั้น ( UnicodeEncodeErrorด้วยข้อมูลที่ไม่ใช่ ascii) ดูโซลูชันของฉันสำหรับรายละเอียด
Antony Hatchkins

111

อ่านและเขียนไฟล์ JSON ด้วย Python 2 + 3; ทำงานร่วมกับ 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)

คำอธิบายของพารามิเตอร์ของjson.dump:

  • indent: ใช้ช่องว่าง 4 ช่องเพื่อเยื้องแต่ละรายการเช่นเมื่อมีการเริ่มเขียนตามคำบอกใหม่ (ไม่เช่นนั้นจะมีทั้งหมดในบรรทัดเดียว)
  • sort_keys: จัดเรียงคีย์ของพจนานุกรม สิ่งนี้มีประโยชน์หากคุณต้องการเปรียบเทียบไฟล์ json ด้วยเครื่องมือ diff / วางไว้ใต้การควบคุมเวอร์ชัน
  • separators: เพื่อป้องกัน Python ไม่ให้เพิ่มช่องว่างที่ต่อท้าย

ด้วยแพ็คเกจ

ดูที่ชุดโปรแกรมอรรถประโยชน์ของฉันmpuเพื่อง่ายสุดและจดจำได้ง่าย ๆ :

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

สร้างไฟล์ JSON

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

การสิ้นสุดไฟล์ทั่วไป

.json

ทางเลือก

สำหรับแอปพลิเคชันของคุณข้อมูลต่อไปนี้อาจสำคัญ:

  • สนับสนุนโดยภาษาโปรแกรมอื่น ๆ
  • การอ่าน / เขียนประสิทธิภาพ
  • ความกะทัดรัด (ขนาดไฟล์)

ดูเพิ่มเติม: การเปรียบเทียบรูปแบบการจัดลำดับข้อมูล

ในกรณีที่คุณกำลังมองหาวิธีสร้างไฟล์การกำหนดค่าคุณอาจต้องการอ่านบทความสั้น ๆ ของฉันไฟล์การตั้งค่าใน Python


2
โปรดทราบว่าการforce_asciiตั้งค่าสถานะนั้นเป็นTrueค่าเริ่มต้น คุณจะมี"\u20ac"ลำดับ6 ไบต์ที่อ่านไม่ได้สำหรับแต่ละไฟล์ในไฟล์ json ของคุณ (รวมถึงอักขระที่ไม่ใช่ ASCII อื่น ๆ )
Antony Hatchkins

ทำไมคุณใช้openสำหรับอ่าน แต่io.openเขียน? เป็นไปได้ไหมที่จะใช้io.openสำหรับการอ่านเช่นกัน? ถ้าเป็นเช่นนั้นพารามิเตอร์อะไรควรผ่าน?
คา Zoltu

23

สำหรับบรรดาของคุณที่กำลังพยายามที่จะถ่ายโอนข้อมูลกรีกหรือภาษา "แปลกใหม่" อื่น ๆ เช่นฉัน แต่ยังมีปัญหา (ข้อผิดพลาด unicode) กับตัวละครแปลก ๆ เช่นสัญลักษณ์สันติภาพ (\ u262E) หรือคนอื่น ๆ ซึ่งมักจะอยู่ในข้อมูลที่จัดรูปแบบ json เช่น Twitter's การแก้ปัญหาอาจเป็นดังนี้ (sort_keys เป็นตัวเลือกที่เห็นได้ชัด):

import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
     f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))

1
+1 ในขณะที่ docs แนะนำ python3 builtin openและ assotiated io.openมากกว่าcodecs.openในกรณีนี้มันยังเป็นการแฮ็กที่เข้ากันได้ดี ใน python2 codecs.openมี "omnivorous" มากกว่า io.open (สามารถ "กิน" ได้ทั้ง str และ unicode หากจำเป็น) เราสามารถพูดได้ว่าการเล่นcodecs.openโวหารนี้ชดเชยการเล่นjson.dumpsโวหารของการสร้างวัตถุประเภทต่าง ๆ ( str/ unicode) ขึ้นอยู่กับการปรากฏตัวของสตริง Unicode ในการป้อนข้อมูล
Antony Hatchkins

10

ฉันไม่มีชื่อเสียงพอที่จะเพิ่มความคิดเห็นดังนั้นฉันเพิ่งเขียนผลการค้นพบ TypeError ที่น่ารำคาญนี้ที่นี่:

โดยทั่วไปฉันคิดว่ามันเป็นข้อบกพร่องในjson.dump()ฟังก์ชั่นใน Python 2เท่านั้น - ไม่สามารถถ่ายโอนข้อมูล Python (พจนานุกรม / รายการ) ที่มีอักขระที่ไม่ใช่ ASCII แม้ว่าคุณจะเปิดไฟล์ด้วยencoding = 'utf-8'พารามิเตอร์ (เช่นไม่ว่าคุณจะทำอะไร) แต่json.dumps()ใช้ได้ทั้ง Python 2 และ 3

เพื่อแสดงสิ่งนี้ให้ติดตามคำตอบของ phihag: โค้ดในคำตอบของเขาจะแบ่งใน Python 2 โดยมีข้อยกเว้นTypeError: must be unicode, not strหากdataมีอักขระที่ไม่ใช่ 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)

มันทำงานได้ดีใน Python 3


ให้เหตุผลเมื่อคุณอ้างว่ามีบางอย่างผิดปกติ ใช้ @nickname เพื่อให้บุคคลนั้นได้รับการแจ้งเตือน คุณไม่สามารถเขียนความคิดเห็น แต่คุณสามารถอ่านความคิดเห็นได้ data = {'asdf': 1}ตามที่ระบุไว้แล้วในคำตอบของฉันที่จะแสดงความคิดเห็นก่อนลอง คุณจะได้รับชื่อเสียงTypeErrorด้วยตัวแปร (ที่สอง) ของคุณ
Antony Hatchkins

เกี่ยวกับensure_ascii- มีความจำเป็นหากคุณต้องการรับเอาต์พุต utf8 "ของจริง" ถ้าไม่มีคุณก็จะมี ascii ธรรมดาที่มี 6 ไบต์ต่อตัวอักษรรัสเซียเมื่อเทียบกับ 2 ไบต์ต่อตัวอักษรด้วยธงนี้
Antony Hatchkins

@AntonyHatchkins คุณถูกต้องสำหรับunicode()ส่วนนี้ ฉันเพิ่งตระหนักสำหรับioแพคเกจในหลาม 2 write()ความต้องการไม่ได้unicode str
ibic

1
รหัสนี้ใช้ได้กับฉันด้วย python2.6.6, Debian (Dec 10 2010) เช่นเดียวกับ python2.7.9 หรือ python3 ตรวจสอบอีกครั้งนะ
Antony Hatchkins

7

เขียนข้อมูลในไฟล์โดยใช้ JSON ใช้json.dump ()หรือjson.dumps ()ใช้ เขียนแบบนี้เพื่อเก็บข้อมูลในไฟล์

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

ตัวอย่างในรายการนี้เก็บไว้ในไฟล์


มันคล้ายกัน แต่มีตัวอย่าง
Vishal Gediya

5

หากต้องการเขียน JSON ด้วยการย่อหน้าให้พิมพ์ "pretty print":

import json

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

นอกจากนี้หากคุณต้องการดีบัก JSON ในรูปแบบที่ไม่เหมาะสมและต้องการข้อความแสดงข้อผิดพลาดที่เป็นประโยชน์ให้ใช้import simplejsonไลบรารี่แทนimport json(ฟังก์ชั่นควรเหมือนกัน)


4
json.dump(data, open('data.txt', 'wb'))

2
นี่เป็นสิ่งเดียวกับคำตอบของ @ phihag แต่ไม่รับประกันว่าจะทำงานได้ตลอดเวลา พิจารณารหัสดังกล่าว: f = open('1.txt', 'w'); f.write('a'); input(). เรียกใช้แล้ว SYGTERM มัน ( Ctrl-Zจากนั้นkill %1บน linux Ctrl-Breakบน Windows) 1.txtจะมี 0 ไบต์ เป็นเพราะการเขียนถูกบัฟเฟอร์และไฟล์ไม่ถูกฟลัชไม่ถูกปิดในขณะที่เกิด SYGTERM withblock รับประกันว่าไฟล์จะถูกปิดเสมอเหมือน block 'try / สุดท้าย' แต่สั้นกว่า
Antony Hatchkins

3

กำลังเขียน JSON ไปยังไฟล์

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)

อ่าน JSON จากไฟล์

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('')

ยินดีต้อนรับสู่ Stack Overflow หากคุณตัดสินใจที่จะตอบคำถามที่เก่ากว่าซึ่งมีคำตอบที่ถูกต้องและถูกต้องแล้วการเพิ่มคำตอบใหม่ในช่วงปลายวันอาจไม่ได้รับเครดิตใด ๆ หากคุณมีข้อมูลใหม่ที่โดดเด่นหรือคุณมั่นใจว่าคำตอบอื่น ๆ นั้นผิดทั้งหมดโดยเพิ่มคำตอบใหม่ แต่ 'อีกคำตอบ' ให้ข้อมูลพื้นฐานเดียวกันเป็นเวลานานหลังจากที่คำถามถูกถามมักจะ ' คุณไม่ได้รับเครดิตมาก (คุณแสดงข้อมูลตัวอย่าง; เป็นสิ่งที่ดี แต่ฉันไม่แน่ใจว่าเพียงพอโดยเฉพาะอย่างยิ่งเมื่อคุณไม่แสดงสิ่งที่ผลิตสำหรับข้อมูลตัวอย่าง)
Jonathan Leffler

ตกลงขอบคุณสำหรับคำแนะนำ
iman

2

หากคุณพยายามที่จะเขียนดาต้าดาต้าแพนด้าลงในไฟล์โดยใช้รูปแบบ json ฉันขอแนะนำนี้

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()

2

คำตอบก่อนหน้าทั้งหมดถูกต้องที่นี่เป็นตัวอย่างที่ง่ายมาก:

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

ป้อนคำอธิบายรูปภาพที่นี่


1

คำตอบที่ยอมรับก็ดี อย่างไรก็ตามฉันพบข้อผิดพลาด "ไม่ใช่ json ต่อเนื่องได้" โดยใช้สิ่งนั้น

นี่คือวิธีที่ฉันแก้ไขมันด้วยopen("file-name.json", 'w')ผลลัพธ์:

output.write(str(response))

แม้ว่าจะไม่ใช่การแก้ไขที่ดีเนื่องจากไฟล์ json ที่สร้างขึ้นจะไม่มีเครื่องหมายคำพูดคู่ แต่ก็เป็นการดีถ้าคุณกำลังมองหาที่รวดเร็วและสกปรก


0

ข้อมูล JSON สามารถเขียนลงไฟล์ได้ดังต่อไปนี้

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

เขียนเป็นไฟล์:

with open('text1.json', 'w') as f:
     json.dump(hist1, f)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.