json.dump lanzando “TypeError: {…} no es serializable JSON” en un objeto aparentemente válido?

Antecedentes : estoy escribiendo un progtwig de python que debería administrar mis archivos de música. Rastrea directorios y coloca los archivos y sus metadatos (a través de mutagen), codificados en JSON, en un archivo como una simple “base de datos”. Tengo el directorio buscando bien, pero cuando bash y guardo la base de datos, o la codifico en JSON, arroja un “TypeError: {…} no es JSON serializable” (las … son algunas claves y valores de un dict , más sobre eso abajo

El problema : el progtwig crea un objeto de diccionario grande siguiendo este formato:

{ "":{ "artist":"", "album":"", "title":""}, ... } 

Cada archivo de canción se indexa a través de este formato. Cuando bash volcar la base de datos en un archivo, obtengo esto:

 Traceback (most recent call last): File "", line 1, in  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 

Con la clave para esa entrada de canción en particular es

 Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids After Sunset.itunes.mp3 

(El formato para la identificación es un poco voluminoso, podría terminar haciendo hashing de eso …)

Así que traté de

 json.dumps({'album': [u"Rooney's Lost Album"], 'title': [u'The Kids After Sunset'], 'artist': [u'Rooney']}) 

que funcionó bien, como lo hizo

 json.dumps({"Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids After Sunset.itunes.mp3":""}) 

Y luego probé esto:

 rooney = "Rooney|Rooney's Lost Album|The Kids After Sunset|The Kids After Sunset.itunes.mp3" json.dumps({rooney:js.db['songsbyid'][rooney]}) 

Que falló con el error de tipo de nuevo.

¿Por qué falla ese objeto con json.dump? Tengo muchos otros objetos con llaves que contienen tubos “|” y apóstrofes “‘” … En este momento, no tengo forma de que nadie más lo pruebe, ¿debo publicar una versión en escabeche del objeto de la base de datos?

Notas adicionales

  • El objeto resultante debajo de json.dumps está bien, así que me pregunto si el problema tiene que ver con el tamaño de la base de datos de alguna manera.

    {rooney: js.db [‘songsbyid’] [rooney]} {“Rooney | Álbum de Lost de Rooney | Los niños después de Sunset | Los niños después de Sunset.itunes.mp3”: {‘album’: [u “Rooney’s Lost Album” ], ‘título’: [u’The Kids After Sunset ‘],’ artista ‘: [u’Rooney’]}}

  • Si excluyo la canción cambiando el nombre de la extensión para que la secuencia de comandos la ignore, otra canción arbitraria provoca el mismo error. Cambié el nombre y excluí esta nueva canción y me encontré con otra canción nueva … No sé cuántas hay.

  • Cambié mi progtwig para rastrear el siguiente subdirectorio más lejano que contiene la canción original problemática, y json.dump generó un TypeError en una canción completamente diferente …

Porque en realidad no es un diccionario; es otro tipo de mapeo que parece un diccionario. Utilice type() para verificar. Pásalo a dict() para obtener un diccionario real de él.

Escribí una clase para normalizar los datos en mi diccionario. El ‘elemento’ en la clase NormalizeData a continuación, debe ser de tipo dict. Y debe reemplazar en __iterate () con su objeto de clase personalizado o con cualquier otro tipo de objeto que desee normalizar.

 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], ): self.element[key] = str(self.element[key]) node = NormalizeData(self.element[key]) node.execute() 

En mi caso, los valores booleanos en mi dictado de Python fueron el problema. Los valores booleanos de JSON están en minúsculas (“true”, “false”), mientras que en Python están en mayúsculas (“True”, “False”). No se pudo encontrar esta solución en cualquier lugar en línea, pero espero que ayude.