在看似有效的对象上抛出“TypeError:{…}不是json serializable”的json.dump?

2024-04-24 06:17:37 发布

您现在位置:Python中文网/ 问答频道 /正文

背景:我正在编写一个python程序,该程序应该管理我的音乐文件。它对目录进行爬网,并将文件及其元数据(通过诱变剂)作为一个简单的“数据库”放在一个文件中,该文件用JSON编码。我可以很好地搜索目录,但是当我尝试保存数据库或编码为JSON时,它会抛出一个“TypeError:{…}不是JSON可序列化的” (那个。。。是dict中的一些键和值,下面详细介绍)

问题:程序按照以下格式生成一个大字典对象:

{
    "<song id>":{
        "artist":"<song artist>",
        "album":"<song album>",
        "title":"<song title>"},
    ...
}

每个歌曲文件都通过这种格式编制索引。当我尝试将数据库转储到文件中时,会得到:

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    sit()
  File "D:\workbench\ideas\musicmanager\v0\spider.py", line 116, in sit
    json.dump(js.db,f,True)
  File "C:\Python27\lib\json\__init__.py", line 181, in dump
    for chunk in iterable:
  File "C:\Python27\lib\json\encoder.py", line 428, in _iterencode
    for chunk in _iterencode_dict(o, _current_indent_level):
  File "C:\Python27\lib\json\encoder.py", line 402, in _iterencode_dict
    for chunk in chunks:
  File "C:\Python27\lib\json\encoder.py", line 402, in _iterencode_dict
    for chunk in chunks:
  File "C:\Python27\lib\json\encoder.py", line 436, in _iterencode
    o = _default(o)
  File "C:\Python27\lib\json\encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: {'album': [u"Rooney's Lost Album"], 'title': [u'The Kids
After Sunset'], 'artist': [u'Rooney']} is not JSON serializable

把那首歌的键

Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids After Sunset.itunes.mp3

(id的格式有点庞大,我可能最终会对其进行散列处理…)

所以我试着

json.dumps({'album': [u"Rooney's Lost Album"], 'title': [u'The Kids
After Sunset'], 'artist': [u'Rooney']})

效果很好

json.dumps({"Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids
After Sunset.itunes.mp3":""})

然后我试着说:

rooney = "Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids
    After Sunset.itunes.mp3"
json.dumps({rooney:js.db['songsbyid'][rooney]})

它再次因类型错误而失败。

为什么这个对象在json.dump中失败?我有很多其他对象的键包含管道“|”和撇号“”。。。目前,我没有办法让其他人来测试这个,我应该发布数据库对象的pickled版本吗?

附加说明

  • json.dumps下面的结果对象很好,所以我想知道这个问题是否与数据库的大小有关?

    {rooney:js.db['songsbyid'][rooney]} {"Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids After Sunset.itunes.mp3": {'album': [u"Rooney's Lost Album"], 'title': [u'The Kids After Sunset'], 'artist': [u'Rooney']}}

  • 如果我通过重命名扩展名来排除歌曲,以便脚本忽略它,则另一首任意歌曲会导致相同的错误。我重新命名并排除了这首新歌,然后遇到了另一首新歌。。。我不知道有多少。

  • 我更改了我的程序以爬行包含原始问题歌曲的下一个最远的子目录,json.dump在完全不同的歌曲上引发了一个TypeError。。。


Tags: 文件theinpyjsonalbumlibline
3条回答

在我的例子中,Python dict中的布尔值是问题所在。JSON布尔值是小写的(“true”,“false”),而在Python中是大写的(“true”,“false”)。在网上找不到这个解决方案,但希望能有帮助。

因为它实际上不是字典;它是另一种映射类型,看起来像字典。使用type()进行验证。将它传递给dict()以从中获取真正的字典。

我写了一个类来规范字典中的数据。下面NormalizeData类中的“element”必须是dict类型。您需要用自定义类对象或任何其他要规范化的对象类型替换u iterate()中的。

class NormalizeData:

    def __init__(self, element):
        self.element = element

    def execute(self):
        if isinstance(self.element, dict):
            self.__iterate()
        else:
            return

    def __iterate(self):
        for key in self.element:
            if isinstance(self.element[key], <ClassName>):
                self.element[key] = str(self.element[key])

            node = NormalizeData(self.element[key])
            node.execute()

相关问题 更多 >