web-dev-qa-db-ja.com

一見有効なオブジェクトに「TypeError:{...} is JSON serializable」をスローするjson.dump?

背景:私はpython音楽ファイルを管理するプログラムを書いています。ディレクトリをクロールし、ファイルとそのメタデータを(mutagen経由で)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の下の結果のオブジェクトは問題ないので、この問題が何らかの形でデータベースのサイズに関係しているのではないかと思いますか?

    {rooney:js.db ['songsbyid'] [rooney]} {"Rooney | Rooney's Lost Album | The Kids After Sunset | The Kids After Sunset.iTunes.mp3":{'アルバム':[u "Rooney's Lost Album" ]、 'title':[u'The Kids After Sunset ']、' artist ':[u'Rooney']}}

  • 拡張機能の名前を変更して曲を除外し、スクリプトで無視されると、別の任意の曲が同じエラーを引き起こします。この新しい曲の名前を変更して除外し、別の新しい曲にぶつかりました...いくつあるかわかりません。

  • 元の問題のある曲を含む次の最も遠いサブディレクトリをクロールするようにプログラムを変更し、json.dumpは完全に異なる曲でTypeErrorを発生させました...

43
drdrez

実際には辞書ではないからです。 looksは辞書のような別のマッピングタイプです。 type()を使用して確認します。 dict()に渡して、そこから実際の辞書を取得します。

私の場合、Python dictのブール値が問題でした。 JSONブール値は小文字(「true」、「false」)であるのに対し、Pythonでは大文字(「True」、「False」)になっています。このソリューションはオンラインのどこにも見つかりませんでしたが、役立つことを願っています。

2
Matthew Park

辞書のデータを正規化するクラスを作成しました。以下の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()
1
Zile Rehman