drdrez
drdrez

Reputation: 951

json.dump throwing "TypeError: {...} is not JSON serializable" on seemingly valid object?

Background: I am writing a python program which should manage my music files. It crawls directories and puts the files and their meta data (via mutagen), encoded in JSON, in a file as a simple "database". I have the directory searching fine, but when I try and save the database, or encode to JSON, it throws a "TypeError: {...} is not JSON serializable" (the ... are some keys and values from a dict, more on that below)

The Problem: The program builds a large dictionary object following this format:

{
    "<song id>":{
        "artist":"<song artist>",
        "album":"<song album>",
        "title":"<song title>"},
    ...
}

Every single song file is indexed via this format. When I try to dump the database to a file, I get this:

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

With the key for that particular song entry being

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

(the format for the id is a little bulky, I might end up hashing that...)

So I tried to

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

which worked fine, as did

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

And then I tried this:

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

Which failed with the type error again.

Why does that object fail with json.dump? I have plenty of other objects with keys containing pipes "|" and apostrophes "'"... At the moment, I have no way for anyone else to test this, should I post a pickled version of the database object?

Additional Notes

Upvotes: 54

Views: 166627

Answers (3)

matthewpark319
matthewpark319

Reputation: 1263

In my case, boolean values in my Python dict were the problem. JSON boolean values are in lowercase ("true", "false") whereas in Python they are in Uppercase ("True", "False"). Couldn't find this solution anywhere online but hope it helps.

Upvotes: 3

Zile Rehman
Zile Rehman

Reputation: 39

I wrote a class to normalize the data in my dictionary. The 'element' in the NormalizeData class below, needs to be of dict type. And you need to replace in the __iterate() with either your custom class object or any other object type that you would like to normalize.

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()

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798576

Because it's not actually a dictionary; it's another mapping type that looks like a dictionary. Use type() to verify. Pass it to dict() to get a real dictionary from it.

Upvotes: 61

Related Questions