如何将JSON数据写入文件?


1121

我将JSON数据存储在变量中data

我想将其写入文本文件进行测试,因此不必每次都从服务器获取数据。

目前,我正在尝试:

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

我收到此错误:

TypeError:必须是字符串或缓冲区,而不是dict

如何解决这个问题?

Answers:


2038

您忘记了实际的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)

8
这可能对序列化很有帮助:stackoverflow.com/questions/4512982/…–
jedierikb

12
您是说json.dump还是json.dumps?
TerminalDilettante

153
@TerminalDilettante json.dump写入文件或类似文件的对象,而json.dumps返回字符串。
phihag

24
顺便说一句:要重新读取数据,请使用:将open('data.txt')作为infile:d = json.load(infile)。请参阅:此答案
克拉斯

9
@denvar不,这个答案是微调的。在Python 3上,json.dump写入文本文件,而不是二进制文件。TypeError如果使用打开文件,您将得到一个wb。在较旧的Python版本上,wnand 均可wb使用。不需要显式编码,因为json.dump默认情况下,的输出仅是ASCII。如果可以确定代码永远不会在旧版Python版本上运行,并且您和JSON文件的处理程序可以正确处理非ASCII数据,则可以指定一个并设置ensure_ascii=False
phihag's

267

要获取utf8编码的文件,而不是Python 2可接受答案中的ascii编码,请使用:

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'to 的参数open仍然是必需的。

为避免将数据的编码副本存储在内存中(结果为dumps),并在Python 2和3中输出utf8编码的字节串,请使用:

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
即使使用2.7,Python 3.x答案也对我有用。2.x答案返回错误:'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128)。因此,如有疑问,请使用3.x答案!
Blairg23

162

我会稍作修改,对上述答案进行回答,那就是编写一个美化的JSON文件,人眼可以更好地阅读。为此,sort_keysTrue和传递indent4个空格字符就可以了。还要注意确保不会将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'
stevek 2014年

1
@SirBenBenji确保要尝试遵循的字符串为:str.decode('utf-8')。
ambodi

1
@SirBenBenji您也可以尝试使用编解码器,正如dinos66在下面指定的那样
Shiv

您还可以通过添加到您的申报编码# -*- coding: utf-8 -*-的家当后
aesede

2
+1表示sort_keys和缩进。@aesede添加此行是不好的,因为它会使该解决方案也适用于python2,但不适用于python2(UnicodeEncodeError使用非ascii数据)。有关详细信息,请参见我的解决方案
安东尼·哈奇金斯

111

使用Python 2 + 3读写JSON文件;与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个空格来缩进每个条目,例如,当开始一个新的dict时(否则所有内容将排在一行中),
  • sort_keys:对字典的键进行排序。如果要使用diff工具比较json文件/将其置于版本控制下,则此功能很有用。
  • 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。您的json文件(以及任何其他非ascii字符)中的"\u20ac"每个字符都有不可读的6个字节的序列
安东尼·哈奇金斯

为什么为什么要用open读书但要用io.open写作呢?是否有可能使用io.open阅读呢?如果是这样,应该传递什么参数?
米卡·佐尔图

23

对于那些尝试转储希腊语或其他“异类”语言(例如我)但也遇到奇怪字符(例如和平符号(\ u262E)或通常包含在json格式数据中的其他字符)的问题(unicode错误)的人例如Twitter,解决方案可能如下(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尽管文档建议python3内置open和assotiated io.opencodecs.open,在这种情况下,它也是一个很好的向下兼容的黑客。在python2 codecs.open中,它比io.open更“杂食”(它可以“吃掉” str和unicode,必要时进行转换)。可以说,这个codecs.open怪癖弥补了根据输入中unicode字符串的存在而json.dumps生成不同类型的对象(str/ unicode)的怪癖。
安东尼·哈奇金斯

10

我没有足够的声誉来添加评论,所以我只在这里写下关于此烦人的TypeError的一些发现:

基本上,我认为这仅json.dump()是Python 2中的函数错误- 即使使用encoding = 'utf-8'参数打开文件,也无法转储包含非ASCII字符的Python(字典/列表)数据。(即,无论您做什么)。但是,json.dumps()可以在Python 2和3上使用。

为了说明这一点,请遵循phihag的答案:他的答案中的代码在Python 2中会中断TypeError: must be unicode, not str,如果data包含非ASCII字符,则会出现exception 。(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(第二个)变体而臭名昭著。
安东尼·哈奇金斯

关于ensure_ascii-如果您想获得“真实的” utf8输出,则很有必要。没有它,您将拥有普通的ascii,每个俄语字母6个字节,而带有此标志的每个字符2个字节。
安东尼·哈奇金斯

@AntonyHatchkins您适合unicode()参加。我只是意识到了io包在Python 2,write()需要unicode,没有str
ibic

1
即使使用python2.6.6,Debian(2010年12月10日),该代码也对我有用。以及python2.7.9或python3。再次检查,请检查。
安东尼·哈奇金斯

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:

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()。运行它,然后对其进行同步(Ctrl-Z然后kill %1在linux上,Ctrl-Break在Windows上)。1.txt将有0个字节。这是因为在发生SYGTERM时,写入被缓冲并且文件没有被刷新也没有关闭。with块保证文件总是像'try / finally'块一样被关闭,但是更短。
安东尼·哈奇金斯

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

欢迎使用堆栈溢出。如果您决定回答一个已经建立并正确答案的较早的问题,那么在当天晚些时候添加一个新答案可能不会给您任何功劳。如果您有一些与众不同的新信息,或者您确信其他答案都是错误的,则一定要添加一个新答案,但是“又一个答案”在问了很长时间后给出相同的基本信息通常是不会的。不能赚很多钱。(您显示了一些样本数据;这很好,但是我不确定是否足够,特别是因为您没有显示样本数据的结果。)
Jonathan Leffler

好的,谢谢您的指导
iman19年

2

如果您尝试使用json格式将pandas数据帧写入文件,我建议您这样做

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.