0

I have a class called Data like this:

class Data:

    def __init__(self, ticker, comments, submissions):
        self.ticker = ticker
        self.comments = comments
        self.submissions = submissions

Where ticker is a string, comments is a list of objects of type Comment and submissions is a list of objectf of type Submission. Comment and Submission have their own fields.

Now I have a list of objects of type Data

I want to itrate through the list and get a JSON String containing all the elements and print it to a file.

My code:

    json_string = json.dumps([ob.__dict__ for ob in data_list])
    f = open("data.json", "w")
    f.write(json_string)
    f.close()

This throws an error of type:

TypeError: Object of type Comment is not JSON serializable

I can't figure out what I'm doing wrong here, does anyone know?

Edit:

Comment class:

class Comment:

def __init__(self, author_name, body, ups):
    self.author_name = author_name
    self.body = body
    self.ups = ups

All fields are string/int

2
  • how does the class Comment look like? Commented Aug 23, 2020 at 15:23
  • I added to the question Commented Aug 23, 2020 at 15:27

2 Answers 2

1

Using default=lambda x: x.__dict__ should help you. It will convert any non serializable objects and you don't have to modify a lot of previous code

import json
# rest of your code
with open("file.json", "w+", encoding="utf-8") as file:
    json.dump(datalist, file, default=lambda x: x.__dict__) #datalist is a list in my case

EDIT :

This was the complete code in my case when testing it:

import json
class Data:
    def __init__(self, ticker="string", comment=[], submissions=[]):
        self.ticker = ticker
        self.comments = comments
        self.submissions = submissions


class Comment:
    def __init__(self, author_name="", body="", ups=1):
        self.author_name = author_name
        self.body = body
        self.ups = ups

class Submission:
    def __init__(self, author_name="", body="", ups=1):
        self.author_name = author_name
        self.body = body
        self.ups = ups

comments = [Comment(ups=i) for i in range(10)]
submissions = [Submission(ups=2*i) for i in range(10)]

datalist = [Data(comment=comments, submissions=submissions) for i in range(5)]

with open("file.json", "w+", encoding="utf-8") as file:
    json.dump(datalist, file, default=lambda x: x.__dict__)
Sign up to request clarification or add additional context in comments.

Comments

1

Classes can't be serialized by default. So either you have to serialize it manually, the same way a you do with Data class, or use a custom json encoder.

manually:

class Data:
   ...
   def to_json(self):
       res = self.__dict__
       res['comments'] = self.comments.__dict__
       return res

however this solution is not really flexible, so rather use a custom JSON encoder, which will automatically handle all objects it encounters during serialization:

# from top of my head something like this:
from json import JSONEncoder
class MyEncoder(JSONEncoder):
    def default(self, o):
        # handle instance of `Data` during json.dump 
        if isinstance(o, Data):
             return o.__dict__
        # handle instance of `Comment` during json.dump
        if isinstance(o, Comment):
             return o.__dict__

        return super().default(o)


json.dumps(data_list, cls=MyEncoder) # custom encoder should handle it

Comments

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.