food_data
is a variable containing JSON data. Using the data, I want to create a list of Food objects, like so
foods = []
for data_row in food_data:
foods.append(Food(data_row))
This is what my Food class looks like as of right now:
class Food(dict):
""" by inheriting from dict, Food objects become automatically serializable for JSON formatting """
def __init__(self, data):
""" create a serialized food object with desired fields """
id = data["id"]
name = data["title"]
image = data["image"]
super().__init__(self, id=id, name=name, image=image)
And here is some example data:
[
{
"id": 738290,
"title": "Pasta with Garlic, Scallions, Cauliflower & Breadcrumbs",
"image": "https://spoonacular.com/recipeImages/716429-312x231.jpg",
},
{
"id": 343245,
"title": "What to make for dinner tonight?? Bruschetta Style Pork & Pasta",
"image": "https://spoonacular.com/recipeImages/715538-312x231.jpg",
}
]
Is there a method I can write for the Food class that will take the data and return a list of different versions of itself?
CodePudding user response:
I would start by not subclassing dict
: there is a better way to make an instance of Food
serializable.
Next, make Food.__init__
dumb: three arguments, used to set three attributes.
Then, define a class method that is responsible for parsing an arbitrary dict
with at least id
, title
, and image
keys to get the values expected by Food.__init__
.
Finally, define a method that turns an instance of Food
back into a dict
(though not necessarily the same dict
that from_dict
uses; generate one that serializes the way you want).
class Food:
def __init__(self, id, name, image):
self.id = id
self.name = name
self.image = image
@classmethod
def from_dict(cls, d):
return cls(id=d['id'], name=d['title'], image=d['image'])
def to_dict(self):
return dict(id=self.id, name=self.name, image=self.image)
foods = [Food.from_dict(d) for d in food_data]
To make your instance serializable, define a customer encoder that uses your to_dict
method,
class FoodEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Food):
return obj.to_dict()
return super().default(obj)
This piggy backs on the default encoder; if the immediate object is a Food
, default
returns a serializable dict
. Otherwise, it defers to its parent to try to serialize it.
Then use that class in the call to json.dumps
.
print(json.dumps(foods, cls=FoodEncoder))
CodePudding user response:
I think in my case I may have been over-engineering my code. But I received many responses that did help me out in other aspects so I'm going to offer them here:
@Juanpa Use a list comprehension
foods = [Food[data] for data in food_data]
@Chepner - unrelated but useful subclass json.JSONEncoder instead of dict for serializability
@Matthias Create a staticmethod within the class to return a list of objects
@staticmethod
def create_foods(food_data):
foods = []
for data_row in food_data:
foods.append(Food(data_row))