Home > Net >  Serializing a list of object instances nested within an object instance python
Serializing a list of object instances nested within an object instance python

Time:11-29

I'm making an app that would allow you to either log in or create a restaurant. As a restaurant owner, you can add/remove/edit refrigerators. My end goal is that I'd have a list of Restaurants that I'd write to a JSON file, and anytime I rerun the app, I can pull that data in and simulate "being a restaurant owner" and edit the fridges for the chosen restaurant.

I essentially want this:

data = {
    restaurants: [
        {
            restaurant: {
            name: "Peppy",
            pw: "123",
            fridges: [
                {
                    fridge: {
                        owner: restaurant.name,
                        contents: []
                    }
                }
            ]
        }
        }
    ]
}

I have the following two classes(showing relevant methods):


class Restaurant:
    def __init__(self, owner, password):
        self.__password = password
        self.owner = owner
        self.__owned_fridges = [] # list of owned fridges

    def add_fridge(self):
        nickname = input("What would you like to name the fridge: ")
        self.__owned_fridges.append(fr(self.owner, nickname))
        print("Fridge added!")
 

class Fridge:
    def __init__(self, owner, nickname):
        self.nickname = nickname
        self.owner = owner
        self.__authorized_users = [owner]
        self.__contents = []

    def add_to_fridge(self):
        if len(self.__contents) == 5:
            print("Your fridge is full!")
        else:
            item = input("What would you like to add : ")
            self.__contents.append(item)

My issue is in serializing this for JSON. I have found that the following works to serialize the restaurant object to JSON, but not the nested fridge objects :

data = {
    'restaurants': []
}

# Testing code
test = res("Jac", "350b534")
test.add_fridge()
test.add_fridge()
data['restaurants'].append(json.dumps(test.__dict__))

I'm relatively new to python, and I come from a js background, so I'm still getting familiar with the syntax. My question is, how do I serialize the inner list of fridges?

CodePudding user response:

Firstly, I'd suggest checking out dataclasses as they will simplify the task of working with classes in Python. With dataclasses, you don't need to define dunder methods like __init__ and __repr__ as they will be generated automatically by default.

For your particular use case, you can solve the issue with serializing a nested class model to a dict / JSON string using an optional default callable that you can pass in to json.dumps. For instance, you can pass a lambda (which is essentially a shorthand function) such as lambda o: o.__dict__, which retrieves the __dict__ attribute for objects that are not inherently serializable to JSON, as shown below.

from __future__ import annotations

import json
from dataclasses import dataclass


@dataclass
class A:
    my_string: str
    b: list[B]


@dataclass
class B:
    my_int: int
    password: str


a = A('test', [B(2, '123'), B(5, '321')])
print(a)
# A(my_string='test', b=[B(my_int=2, password='123'), B(my_int=5, password='321')])

print(json.dumps(a, default=lambda o: o.__dict__))
# {"my_string": "test", "b": [{"my_int": 2, "password": "123"}, {"my_int": 5, "password": "321"}]}

But note that dataclasses also provides a helper function asdict if you need to convert a dataclass instance to a dict instance first.


Though, if you have a more advanced use case - for example, de-serializing JSON data to a nested class model, or mapping a dataclass field such as password to another JSON key such as pw as in the listed example - I'd suggest checking out a serialization library like the dataclass-wizard, which works well with a nested dataclass model as above.

  • Related