ChatGPT解决这个技术问题 Extra ChatGPT

如何将 JSON 数据写入文件?

如何将存储在字典 data 中的 JSON 数据写入文件?

f = open('data.json', 'wb')
f.write(data)

这给出了错误:

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

对于打开文件时的标志:这里,我们在参数中使用了“w”字母,表示写入,如果库中不存在则创建文件加号表示读取和写入,guru99.com/reading-and-writing-files-in-python.html#1
pathlib 与一行一起使用:Path("data.json").write_text(json.dumps(data))

M
Mateen Ulhaq

data 是 Python 字典。在写入之前需要将其编码为 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)

请参阅 json 文档。


这可能有助于序列化:stackoverflow.com/questions/4512982/…
你的意思是 json.dump 还是 json.dumps?
@TerminalDilettante json.dump 写入文件或类似文件的对象,而 json.dumps 返回一个字符串。
顺便说一句:重新读取数据使用:使用 open('data.txt') 作为 infile:d = json.load(infile)。请参阅:this answer
@denvar 不,这个答案经过精心调整。在 Python 3 上,json.dump 写入文本文件,而不是二进制文件。如果文件是用 wb 打开的,您会得到一个 TypeError。在较旧的 Python 版本上,wwb 都可以工作。不需要显式编码,因为 json.dump 的输出默认为仅 ASCII。如果您可以确定您的代码永远不会在旧版 Python 版本上运行,并且您和 JSON 文件的处理程序可以正确处理非 ASCII 数据,您可以指定一个并设置 ensure_ascii=False
A
Antony Hatchkins

要在 Python 2 接受的答案中获取 utf8 编码文件而不是 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 上,openencoding='utf-8' 参数仍然是必需的。

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

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 所建议)添加到 dumpdumps 的参数来进一步提高可读性。这样,您将在 json 文件中获得一个很好的缩进排序结构,但代价是文件大小稍大。


unicode 是多余的 - json.dumps 的结果已经是一个 unicode 对象。请注意,这在 3.x 中失败了,其中输出文件模式的整个混乱已被清除,并且 json 始终使用字符串(和字符 I/O)而不是字节。
在 2.x 中,type(json.dumps('a'))<type 'str'>。甚至 type(json.dumps('a', encoding='utf8')) 也是 <type 'str'>
是的,在 3.x 中,json 使用字符串,但默认编码是 ascii。即使在 3.x 中,您也必须明确告诉它您想要 utf8。更新了答案。
即使我使用的是 2.7,Python 3.x 的答案也对我有用。 2.x 答案返回错误:'ascii' codec can't decode byte 0xf1 in position 506755: ordinal not in range(128)。因此,如有疑问,请使用 3.x 答案!
对我来说 codecs.getwriter 在 python 3 中是必需的。否则:json.dump( recipe , ensure_ascii=False) TypeError: dump() missing 1 required positional argument: 'fp'
N
Neuron

我会用上述答案稍作修改来回答,那就是编写一个人眼可以更好地阅读的美化 JSON 文件。为此,将 sort_keys 作为 Trueindent 传递 4 个空格字符,一切顺利。还要注意确保 ascii 代码不会写入您的 JSON 文件中:

with open('data.txt', 'w') as out_file:
     json.dump(json_data, out_file, sort_keys = True, indent = 4,
               ensure_ascii = False)

仍然得到UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc'
@SirBenBenji 确保您尝试写入的字符串遵循:str.decode('utf-8')。
@SirBenBenji 您也可以尝试使用编解码器,正如 dinos66 在下面指定的那样
您还必须通过在 shebang 后添加 # -*- coding: utf-8 -*- 来声明您的编码
+1 排序键和缩进。 @aesede 添加这一行并不好,因为它会让人觉得这个解决方案也适用于 python2,但它不适用(UnicodeEncodeError 与非 ascii 数据)。有关详细信息,请参阅 my solution
M
Martin Thoma

使用 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:对字典的键进行排序。如果您想使用差异工具比较 json 文件/将它们置于版本控制之下,这将非常有用。

分隔符:防止 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

备择方案

CSV:超级简单的格式(读写)

JSON:非常适合编写人类可读的数据;非常常用(读写)

YAML:YAML 是 JSON 的超集,但更易于阅读(读写,JSON 和 YAML 的比较)

pickle:一种 Python 序列化格式(读写)

MessagePack(Python 包):更紧凑的表示(读写)

HDF5(Python 包):适用于矩阵(读写)

XML: 也存在 *sigh* (读 & 写)

对于您的应用程序,以下内容可能很重要:

其他编程语言的支持

读/写性能

紧凑性(文件大小)

另请参阅:Comparison of data serialization formats

如果您正在寻找一种制作配置文件的方法,您可能需要阅读我的短文 Configuration files in Python


请注意,force_ascii 标志默认为 True。对于 json 文件中的每个 (以及任何其他非 ascii 字符),您将拥有不可读的 6 字节 "\u20ac" 序列。
为什么您使用 open 阅读而使用 io.open 写作?是否也可能使用 io.open 进行阅读?如果是这样,应该传递什么参数?
d
dinos66

对于那些试图转储希腊语或其他“外来”语言(例如我)但也遇到奇怪字符(例如和平符号 (\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 虽然文档推荐 python3 内置 open 和相关的 io.open 而不是 codecs.open,但在这种情况下,它也是一个很好的向后兼容的 hack。在 python2 中,codecs.open 比 io.open 更“杂食”(它可以“吃”str 和 unicode,必要时进行转换)。可以说,这种 codecs.open 怪癖补偿了 json.dumps 怪癖,即根据输入中是否存在 unicode 字符串生成不同类型的对象 (str/unicode)。
A
Antony Hatchkins

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

基本上,我认为这只是 Python 2json.dump() 函数中的一个错误 - 它不能转储包含非 ASCII 字符的 Python(字典/列表)数据,甚至 em> 您使用 encoding = 'utf-8' 参数打开文件。 (即无论你做什么)。但是,json.dumps() 适用于 Python 2 和 3。

为了说明这一点,请跟进 phihag 的回答:如果 data 包含非 ASCII 字符,则他的回答中的代码在 Python 2 中会出现异常 TypeError: must be unicode, not str 中断。 (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 输出,则有必要。没有它,您将拥有每个俄文字母 6 个字节的普通 ascii,而不是带有此标志的每个字符 2 个字节。
@AntonyHatchkins 您是正确的 unicode() 部分。我刚刚意识到 Python 2 中的 io 包,write() 需要 unicode,而不是 str
即使使用 python2.6.6,Debian(2010 年 12 月 10 日),此代码也适用于我。以及 python2.7.9 或 python3。请再检查一次,请。
V
Vishal Gediya

使用 JSON 在文件中写入数据,使用 json.dump() 或 json.dumps()。像这样写来将数据存储在文件中。

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

列表中的此示例存储到文件中。


它很相似,但提供了示例
A
Alexander
json.dump(data, open('data.txt', 'wb'))

这与@phihag 的答案相同,但不能保证始终有效。考虑这样的代码:f = open('1.txt', 'w'); f.write('a'); input()。运行它,然后 SYGTERM 它(Linux 上是 Ctrl-Z,然后是 kill %1,Windows 上是 Ctrl-Break)。 1.txt 将有 0 个字节。这是因为在 SYGTERM 发生的那一刻,写入被缓冲并且文件既没有刷新也没有关闭。 with 块保证文件总是像“try/finally”块一样关闭,但更短。
J
James Wierzba

要编写带有缩进的 JSON,“漂亮的打印”:

import json

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

此外,如果您需要调试格式不正确的 JSON,并且需要有用的错误消息,请使用 import simplejson 库,而不是 import json(功能应该相同)


open('data.json') 不以只读模式打开文件吗?
g
grepit

之前的所有答案都是正确的,这是一个非常简单的例子:

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

https://i.stack.imgur.com/1CNhG.png


F
Franco Miguel Contreras

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

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

A
Ashok Kumar Jayaraman

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)

o
ofundefined

接受的答案很好。但是,我使用它遇到了“不是 json 可序列化”错误。

以下是我使用 open("file-name.json", 'w') 作为输出修复它的方法:

output.write(str(response))

虽然它不是一个很好的解决方法,因为它创建的 json 文件不会有双引号,但是如果您正在寻找快速和肮脏的东西,那就太好了。


K
Kavindu Ravishka

在将字典作为 json 写入文件之前,您必须使用 json 库将该字典转换为 json 字符串。

import json

data = {
    "field1":{
        "a": 10,
        "b": 20,
    },
    "field2":{
        "c": 30,
        "d": 40,
    },
}

json_data = json.dumps(json_data)

您还可以为 json 数据添加缩进以看起来更漂亮。

json_data = json.dumps(json_data, indent=4)

如果你想在变成json之前对key进行排序,

json_data = json.dumps(json_data, sort_keys=True)

您也可以使用这两者的组合。

请参阅此处的 json documentation 了解更多功能

最后你可以写入一个json文件

f = open('data.json', 'wb')
f.write(json_data)

q
questionto42standswithUkraine

这只是对 json.dumps 用法的一个额外提示(这不是对问题问题的回答,而是对于那些必须转储 numpy 数据类型的人的技巧):

如果字典中有 NumPy 数据类型,json.dumps() 需要一个额外的参数,积分归 TypeError: Object of type 'ndarray' is not JSON serializable,它还会修复 TypeError: Object of type int64 is not JSON serializable 等错误:

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for np types """
    def default(self, obj):
        if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
                            np.int16, np.int32, np.int64, np.uint8,
                            np.uint16, np.uint32, np.uint64)):
            return int(obj)
        elif isinstance(obj, (np.float_, np.float16, np.float32,
                              np.float64)):
            return float(obj)
        elif isinstance(obj, (np.ndarray,)):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

然后运行:

import json

#print(json.dumps(my_data[:2], indent=4, cls=NumpyEncoder)))
with open(my_dir+'/my_filename.json', 'w') as f:
    json.dumps(my_data, indent=4, cls=NumpyEncoder)))

在 np.array() 的情况下,您可能还希望返回一个字符串而不是一个列表,因为数组打印为分布在行上的列表,如果您有很大或很多数组,这将破坏输出。警告:稍后从转储字典中访问项目以将它们作为原始数组返回更加困难。但是,如果您不介意只有一个数组字符串,这会使字典更具可读性。然后交换:

        elif isinstance(obj, (np.ndarray,)):
            return obj.tolist()

和:

        elif isinstance(obj, (np.ndarray,)):
            return str(obj)

要不就:

        else:
            return str(obj)

做一些非常简单的事情是多么迂回的方式
@user32882 是的,这也让我感到惊讶。像json.dumps这样的标准的弱点。它被否决了,也许是因为没有人认为它会那么复杂(包括我),它并没有真正回答这个问题,但就我而言,我需要它。
请看一下接受的答案。这不应该超过几行代码。
@ user32882 据我所知,接受的答案无法导出 numpy 数据类型,这就是我添加此答案的原因。不过,我不确定 json.dumpjson.dumps 之间的 numpy 数据类型是否存在差异,我现在不能花时间测试这个,我想我还是测试了这个。此答案不应取代已接受的答案,而是添加此特殊情况(一点也不特殊,numpy 数据类型很常见)。
@user32882 阅读您的评论,您还没有理解这个答案。此处或多或少重复了接受的答案(此处使用 dumps 而不是 dump,以便您可以使用参数),并且刚刚添加了使 numpy 导出成为可能的类。没有什么反对为正确的缘故投票,但请考虑一下。