Home > front end >  how to create a python object from a json paylaod, without declaring each variable manually
how to create a python object from a json paylaod, without declaring each variable manually

Time:10-18

basically I've got a booking class with fields each declared manually. I am curious if theres a more neat solution for the given task.

class Booking:
    def __init__(self, json_data):
        self.referenceNumber = json_data["referenceNumber"]
        self.fromDate = json_data["fromDate"]
        self.preferredDate1 = json_data["preferredDate1"]
        self.preferredTimeFrom = json_data["preferredTimeFrom"]
        self.time = json_data["time"]
        self.partySize = json_data["partySize"]
        self.budgetAmountTotal = json_data["budgetAmountTotal"]
        self.budgetAmountPerPerson = json_data["budgetAmountPerPerson"]
        self.budgetCurrencySign = json_data["budgetCurrencySign"]
        self.venueName = json_data["venueName"]
        self.venueId = json_data["venueId"]
        self.cityName = json_data["cityName"]
        self.clientName = json_data["clientName"]
        self.clientContactName = json_data["clientContactName"]
        self.status = json_data["status"]
        self.statusText = json_data["statusText"]
        self.assigneeId = json_data["assigneeId"]
        self.assignee = json_data["assignee"]
        self.lastAction = json_data["lastAction"]
        self.inquiryChannel = json_data["inquiryChannel"]
        self.venueDateFormat = json_data["venueDateFormat"]
        self.bookingId = json_data["bookingId"]
        self.inquiryHold = json_data["inquiryHold"]
        self.isSpaceSelectedForHolds = json_data["isSpaceSelectedForHolds"]
        self.id = json_data["id"]

bonus if i am not given an unresolved reference warning when I am calling for the attribute.

CodePudding user response:

A simple self.__dict__.update(json_data) might do the trick.

CodePudding user response:

Given the code in the question, access to attributes would be, for example, in the style of:

Booking().fromDate

However, if you don't mind accessing the value by its key name then you can greatly simplify the code as follows:

class Booking:
  def __init__(self, json_data):
    self._json = json.data
  def __getitem__(self, key):
    return self._json.get(key)

Then (for example)...

pd = {'fromDate': '2022/10/18'}

print(Booking(pd)['fromDate'])

CodePudding user response:

How about this?

def set_attr_from_json(obj, json_data):
    for key, value in json_data.items():
        setattr(obj, key, value)
        
class Booking:                
    def __init__(self, json_data):
        set_attr_from_json(self, json_data)

CodePudding user response:

Since you want to control how your class attributes should be built, I think you should use metaclass like this

import json
from types import SimpleNamespace

class BookingMeta(type):
    def __call__(self, json_data):
        obj = super().__call__(json_data)
        obj = json.loads(json.dumps(json_data), object_hook=lambda d: SimpleNamespace(**d))
        return obj

class Booking(metaclass=BookingMeta):                
    def __init__(self, json_data):
        pass


b = Booking({"name": {"first_name": "hello", "last_name": "world"}, "age": 23, "sub": ["maths", "Science"]})
print(b.name.first_name)
print(b.age)
#hello
#23
  • Related