49

背景: 音楽ファイルを管理する Python プログラムを作成しています。ディレクトリをクロールし、JSON でエンコードされたファイルとそのメタデータ (mutagen 経由) を単純な「データベース」としてファイルに配置します。ディレクトリを正常に検索していますが、データベースを保存しようとしたり、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": {'album': [u"Rooney's Lost Album" ], 'title': [u'The Kids After Sunset'], 'アーティスト': [u'Rooney']}}

  • スクリプトがそれを無視するように拡張子の名前を変更して曲を除外すると、別の任意の曲で同じエラーが発生します。この新曲の名前を変更して除外したところ、別の新曲に出くわしました...いくつあるのかわかりません。

  • 元の問題の曲を含む次の最も遠いサブディレクトリをクロールするようにプログラムを変更したところ、まったく別の曲で json.dump が TypeError を発生させました...

4

3 に答える 3

60

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

于 2012-06-03T17:57:07.980 に答える
4

私の場合、Python dict のブール値が問題でした。JSON ブール値は小文字 (「true」、「false」) ですが、Python では大文字 (「True」、「False」) です。この解決策はオンラインのどこにも見つかりませんでしたが、役に立てば幸いです。

于 2018-08-21T15:53:30.610 に答える
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()
于 2014-02-06T16:00:07.040 に答える