json.dump在看似有效的对象上抛出“TypeError:{...}不是JSON可序列化的”?

时间:2012-06-03 17:52:16

标签: python json typeerror

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

附加说明

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

      
        
          

    {鲁尼:js.db [ 'songsbyid'] [鲁尼]}       {“鲁尼|鲁尼的失落专辑|日落之后的孩子们|孩子们       在Sunset.itunes.mp3“:{'专辑':[u”鲁尼的失落专辑“]之后,       'title':[日落时的孩子们],'艺术家':[u'Rooney']}}

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

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

3 个答案:

答案 0 :(得分:47)

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

答案 1 :(得分:1)

我写了一个类来规范化词典中的数据。 &#39;元素&#39;在下面的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()

答案 2 :(得分:1)

就我而言,Python字典中的布尔值就是问题所在。 JSON布尔值使用小写字母(“ true”,“ false”),而在Python中则使用大写字母(“ True”,“ False”)。找不到在线解决方案,但希望对您有所帮助。