1

I have a song class, which holds the attributes to a song, and it is a custom class. I also have a list of songs in a list called track list. When I try to json.dump the list, I get an error that says :

TypeError: Object of type 'Song' is not JSON serializable

How would I go about converting this list of songs to json?

Here is the additional relevant code that returns the error:

class Song:
def __init__(self, sname, sartist, coverart, albname, albartist, spotid):
    self.sname = sname
    self.sartist = sartist
    self.coverart = coverart
    self.albname = albname
    self.albartist = albartist
    self.spotid = spotid

tracklist = createDict(tracks) ##creates the list of songs, works fine
jsontracks = json.dumps(tracklist)
pp.pprint(jsontracks)

Thanks

3
  • Are you able to post a sample of your data? Also, you will need to indent 'def init...'. Commented May 2, 2020 at 3:19
  • This is explained in the documentation. See the description of the default parameter. Commented May 2, 2020 at 3:26
  • Does this answer your question? How to make a class JSON serializable Commented May 2, 2020 at 3:26

1 Answer 1

9

I've solved this by adding an encode() method to the class:

def encode(self):
    return self.__dict__

and adding some arguments to json.dumps:

jsontracks = json.dumps(tracklist, default=lambda o: o.encode(), indent=4)

This will "crawl" down your class tree (if you have any child classes) and encode every object as a json list/object automatically. This should work with just about any class and is fast to type. You may also want to control which class parameters get encoded with something like:

def encode(self):
    return {'name': self.name,
            'code': self.code,
            'amount': self.amount,
            'minimum': self.minimum,
            'maximum': self.maximum}

or a little bit faster to edit (if you're lazy like me):

def encode(self):
    encoded_items = ['name', 'code', 'batch_size', 'cost',
                     'unit', 'ingredients', 'nutrients']
    return {k: v for k, v in self.__dict__.items() if k in encoded_items}

full code:

import json


class Song:
    def __init__(self, sname, sartist, coverart, albname, albartist, spotid):
        self.sname = sname
        self.sartist = sartist
        self.coverart = coverart
        self.albname = albname
        self.albartist = albartist
        self.spotid = spotid

    def encode(self):
        return self.__dict__


tracklist = [
    Song('Imagine', 'John Lennon', None, None, None, None),
    Song('Hey Jude', 'The Beatles', None, None, None, None),
    Song('(I Can\'t Get No) Satisfaction', 'The Rolling Stones', None, None, None, None),
]

jsontracks = json.dumps(tracklist, default=lambda o: o.encode(), indent=4)
print(jsontracks)

output:

[
    {
        "sname": "Imagine",
        "sartist": "John Lennon",
        "coverart": null,
        "albname": null,
        "albartist": null,
        "spotid": null
    },
    {
        "sname": "Hey Jude",
        "sartist": "The Beatles",
        "coverart": null,
        "albname": null,
        "albartist": null,
        "spotid": null
    },
    {
        "sname": "(I Can't Get No) Satisfaction",
        "sartist": "The Rolling Stones",
        "coverart": null,
        "albname": null,
        "albartist": null,
        "spotid": null
    }
]
Sign up to request clarification or add additional context in comments.

1 Comment

This not work with static attributes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.