json.dump 在看似有效的对象上抛出“TypeError: ... is not JSON serializable”?

Posted

技术标签:

【中文标题】json.dump 在看似有效的对象上抛出“TypeError: ... is not JSON serializable”?【英文标题】:json.dump throwing "TypeError: ... is not JSON serializable" on seemingly valid object?json.dump 在看似有效的对象上抛出“TypeError: ... is not JSON serializable”? 【发布时间】:2012-06-08 00:18:08 【问题描述】:

背景:我正在编写一个 python 程序来管理我的音乐文件。它爬取目录并将文件及其元数据(通过诱变剂)以 JSON 编码,作为简单的“数据库”放入文件中。我的目录搜索很好,但是当我尝试保存数据库或编码为 JSON 时,它会抛出“TypeError:... is not JSON serializable” (... 是 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 而失败?我有很多其他对象,其键包含管道“|”和撇号“'”...目前,我无法让其他人对此进行测试,我应该发布数据库对象的腌制版本吗?

附加说明

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

鲁尼:js.db['songsbyid'][鲁尼] “鲁尼|鲁尼丢失的专辑|日落后的孩子们|孩子们 在 Sunset.itunes.mp3": 'album': [u"Rooney's Lost Album"] 之后, 'title': [u'The Kids After Sunset'], 'artist': [u'Rooney']

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

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

【问题讨论】:

您是否考虑过打印出来的内容可能不是它试图编码的内容?如果db 类定义了__repr__,您可能会看到一些看起来可以JSON 的东西被打印出来,但它试图编码的实际东西并不是这样。 谢谢@Amber,这不是我的数据库字典,它原来是歌曲元数据的诱变剂返回值 使用json.dumps(data, default=lambda x: None) 来抑制TypeErrors 并转储data 中无法序列化为null 的任何内容 【参考方案1】:

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

【讨论】:

我尝试在整个数据库对象的 json.dump 和“rooney:js.db['songsbyid'][rooney]” sn 中的对象周围使用 dict() -p(第一个罪魁祸首歌曲条目),我仍然收到类型错误...:/ 问题在我的代码中更深层次——我使用诱变剂获取音乐文件的元数据,它返回的值不能是实际列表。对它返回的值使用 dict() 解决了这个问题。 我发布此内容是为了让其他 google 人受益,他们在尝试此建议时感到沮丧,并且感觉有点像 Patrick Star 在与 Man Ray 交谈时,他们断言某事确实是一个 dict 的大量方式。如果您的字典inside 中的任何内容不可序列化,即使您在顶层序列化字典,您也会收到此类型错误。尝试 print(str(yourdict)) 并将其输出与错误输出进行比较以查看哪个对象。【参考方案2】:

我编写了一个类来规范化字典中的数据。下面的 NormalizeData 类中的“元素”需要是 dict 类型。并且您需要在 __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()

【讨论】:

【参考方案3】:

就我而言,我的 Python dict 中的布尔值是问题所在。 JSON 布尔值是小写的(“true”、“false”),而在 Python 中它们是大写的(“True”、“False”)。在网上的任何地方都找不到此解决方案,但希望对您有所帮助。

【讨论】:

以上是关于json.dump 在看似有效的对象上抛出“TypeError: ... is not JSON serializable”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Integer.parseInt 在看起来有效的输入上抛出 NumberFormatException?

json_extract_path_text('[]', 'some_key') 在有效的 json 字符串上抛出错误

JsonSerializable - fromJson 在嵌套对象上抛出 _InternalLinkedHashMap<dynamic, dynamic> 异常

OpenCV SVM 在火车上抛出异常,“错误参数(只有一个类)”

C# LINQ/EF 在具有值转换的属性上抛出无效强制转换

杰克逊映射器在三星 SM-T580 上抛出“冲突的二传手定义”