1445

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

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

目前,我正在尝试这个:

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

我收到了这个错误:

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

如何解决这个问题?

4

14 回答 14

2604

您忘记了实际的 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)
于 2012-09-06T22:23:14.897 回答
285

要在 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 上,encoding='utf-8'参数 toopen仍然是必要的。

为了避免在内存中存储数据的编码副本(结果)并在 Python 2 和 3 中dumps输出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

通过向or的参数添加标志indent=4, sort_keys=True(如dinos66所建议的)进一步提高可读性。这样,您将在 json 文件中获得一个很好的缩进排序结构,但代价是文件大小稍大。dumpdumps

于 2013-02-14T08:22:36.483 回答
173

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

with open('data.txt', 'w') as outfile:
     json.dump(jsonData, outfile, sort_keys = True, indent = 4,
               ensure_ascii = False)
于 2013-12-25T20:04:24.653 回答
125

使用 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 文件/将它们置于版本控制之下,这将非常有用。
  • 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 中的配置文件

于 2016-06-13T16:43:33.533 回答
26

对于那些试图转储希腊语或其他“外来”语言(例如我)但也遇到奇怪字符(例如和平符号 (\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))
于 2015-07-10T14:45:29.270 回答
13

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

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

为了说明这一点,跟进 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 中运行良好。

于 2016-01-03T06:52:36.360 回答
11

Write a data in file using JSON use json.dump() or json.dumps() used. write like this to store data in file.

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

this example in list is store to a file.

于 2015-12-24T10:58:21.390 回答
6

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

import json

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

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

于 2018-12-13T22:38:01.237 回答
6
json.dump(data, open('data.txt', 'wb'))
于 2016-02-29T20:16:51.557 回答
4

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

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

在此处输入图像描述

于 2018-10-10T05:36:43.863 回答
3

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

destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
于 2017-06-03T07:48:30.773 回答
2

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)
于 2018-11-01T12:00:47.470 回答
2

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

这是我将其修复open("file-name.json", 'w')为输出的方法:

output.write(str(response))

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

于 2018-10-15T04:10:56.743 回答
-2

这只是对使用的额外提示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)
于 2021-09-13T12:16:53.287 回答