user17090811
user17090811

Reputation: 308

How to convert dict to class attributes in Python

Instead of using a dict to store and pass data we are going completely OOPS approach of storing the data as class attributes and call the get methods defined according to need.

In Java i was able to achieve this but having some trouble in Python. Any Solution would be helpful.

import json

class InputModel:
    def __init__(self, input_payload):
        self.id1 = input_payload["id1"]
        self.route = RouteModel(input_payload["route"])
        self.id2 = input_payload["id2"]
        self.id3 = input_payload["id3"]
        self.id4 = input_payload["id4"]
        self.id5 = input_payload["id5"]

        def get_id1(self):
            return self.id1

        #similar for other ids


class RouteModel:
    def __init__(self, input_payload_route):
        self.id6 = input_payload_route["id6"]
        self.id7 = input_payload_route["id7"]
       
        def get_id6(self):
            return self.id6

        #similar for other ids
        
        

json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)
print(im.get_id1())
print(im.get_id6())

not able to access the nested class attributes

Upvotes: 1

Views: 1214

Answers (4)

user17090811
user17090811

Reputation: 308

After going through answers provided, mostly have defined instance attributes and not class attributes.

Correct me if I'm wrong here but I think this is how class attributes are defined right?

import json

class InputModel:
    def __init__(self, input_payload):
        InputModel.id1 = input_payload["id1"]
        InputModel.route = RouteModel(input_payload["route"])
        InputModel.id2 = input_payload["id2"]
        InputModel.id3 = input_payload["id3"]
        InputModel.id4 = input_payload["id4"]
        InputModel.id5 = input_payload["id5"]

        def get_id1():
            return InputModel.id1
        #OR
        #@classmethod
        #def get_id1(cls):
        #    return cls.id1

        #similar for other ids


class RouteModel:
    def __init__(self, input_payload_route):
        RouteModel.id6 = input_payload_route["id6"]
        RouteModel.id7 = input_payload_route["id7"]
       
        def get_id6():
            return RouteModel.id6

        #similar for other ids
        
        

json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)

InputModel(json_dict)
print(InputModel.get_id1())
print(InputModel.route.get_id6())
print(RouteModel.get_id6())

Upvotes: 0

Wups
Wups

Reputation: 2569

If I understand your question correctly, you want to be able to access the ids directly as attributes, no matter how deep they are nested in the dictionary.
This solution creates the attributes recursively:

import json

class InputModel:
    def __init__(self, payload):
        self.create_attrs(payload)

    def create_attrs(self, d):
        for key, value in d.items():
            # if the value is a dict, call create_attrs recursively
            if isinstance(value, dict):
                self.create_attrs(value)
            else:
                # create an attribute key=value, e.g. id1="string"
                setattr(self, key, value)


json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)

print(im.id1)
print(im.id6)

Upvotes: 2

Mandera
Mandera

Reputation: 3027

The problem is that you are only defining get_id* in your local scope, you need to assign it to the instance if you insist on defining it inside the __init__ method.

I minimized your code example to isolate your issue.

class RouteModel:
    def __init__(self):
        self.id6 = "foo"

        def get_id6(self_=self):
            return self_.id6

        self.get_id6 = get_id6

rm = RouteModel()
print(rm.get_id6())

>>> "foo"

Upvotes: 1

NSegal
NSegal

Reputation: 56

Seems like you went for 1 extra indent in your class methods, thus you couldn't reach them.

Also, to reach id6 of RouteModel, you had to refer to 'route' first:

import json

class InputModel:
    def __init__(self, input_payload):
        self.id1 = input_payload["id1"]
        self.route = RouteModel(input_payload["route"])
        self.id2 = input_payload["id2"]
        self.id3 = input_payload["id3"]
        self.id4 = input_payload["id4"]
        self.id5 = input_payload["id5"]

    def get_id1(self):
        return self.id1

        #similar for other ids


class RouteModel:
    def __init__(self, input_payload_route):
        self.id6 = input_payload_route["id6"]
        self.id7 = input_payload_route["id7"]
    
    def get_id6(self):
        return self.id6

        #similar for other ids
        
        

json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)
print(im.get_id1())
print(im.route.get_id6())

Output:

string
string

Upvotes: 2

Related Questions