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)
来抑制TypeError
s 并转储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> 异常