-1

In a project I have to output json file for some sort of entities. so this question is somehow a simplified version of my issue. Imagine I got these classes which I am gonna need their dict of properties and attributes as json output:

from random import randint

class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def out_dict(self):
        return self.__dict__

class B:
    def __init__(self, B_a, list_of_A):
        self.b_arg = B_a
        self.list_of_A = list_of_A
    def out_dict(self):
        return self.__dict__

class C:
    def __init__(self, C_a, list_of_B):
        self.c_arg = C_a
        self.list_of_B = list_of_B
    def out_dict(self):
        return self.__dict__

list_of_A = [A(randint(0,100), randint(0,100)) for _ in range(5)]
list_of_B = [B(5, list_of_A) for _ in range(3)]
c = C(10, list_of_B)
print(c.out_dict())

the output of above code is:

{'c_arg': 10,
'list_of_B': [<__main__.B at 0x207613625c0>,
 <__main__.B at 0x2076110bdd8>,

As you see, the objects are nested and the output does not mention all the attributes of classes in details. In the other hand, I need some output like this:

{"C":
   {"list_of_B":[
    "B0": {
           {"list_of_A":
                {["0":{"a":10, "b":21}, "2":{"a":1, "b":3}, 
                  "1":{"a":10, "b":21}, "2":{"a":54, "b":12},
                  "2":{"a":10, "b":21}, "2":{"a":12, "b":32},
                ]}
            "b_arg": 27
            }


        },
    "B1": {
           {"list_of_A":
                {["0":{"a":10, "b":21}, "2":{"a":1, "b":3}, 
                  "1":{"a":10, "b":21}, "2":{"a":54, "b":12},
                  "2":{"a":10, "b":21}, "2":{"a":12, "b":32},
                ]}
            "b_arg": 27
            }


        },
               ]
    "c_arg": 95
   }
}

How can I get retrieve details in such circumstances.?

I need them to be outputted as json.

Thanks

martineau
  • 119,623
  • 25
  • 170
  • 301
Masoud Masoumi Moghadam
  • 1,094
  • 3
  • 23
  • 45
  • For each object in `out_dict()` you need to get the respective `out_dict()` recursively. – mkrieger1 Feb 08 '20 at 11:16
  • 1
    Possible duplicate of https://stackoverflow.com/questions/1036409/recursively-convert-python-object-graph-to-dictionary – mkrieger1 Feb 08 '20 at 11:18

2 Answers2

1

If you want to have fairly ordinary, but custom objects which are in a hierarchy, but can convert themselves to a hierarchy of python types (ints, strings, lists and dicts), then you have to arrange that they call out_dict() recursively for you.

Try this:

from random import randint

class OutDict:
    def out_dict(self):
        out = {}
        for k,v in self.__dict__.items():
            if hasattr(v,'out_dict'):
                print('out_dict')
                out[k] = v.out_dict()
            elif isinstance(v,list):
                out[k] = self.out_list(v)
            else:
                out[k] = v
        return out

    def out_list(self, values):
        return [v.out_dict() if hasattr(v,'out_dict') else v for v in values]

class A(OutDict):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class B(OutDict):
    def __init__(self, B_a, list_of_A):
        self.b_arg = B_a
        self.list_of_A = list_of_A

class C(OutDict):
    def __init__(self, C_a, list_of_B):
        self.c_arg = C_a
        self.list_of_B = list_of_B

list_of_A = [A(randint(0,100), randint(0,100)) for _ in range(5)]
list_of_B = [B(5, list_of_A) for _ in range(3)]
c = C(10, list_of_B)
print(c.out_dict())

Note how I have created a custom base class OutDict which has the out_dict() method (and a helper out_list() method) which classes A, B and C derive from.

Sample Output:

{'c_arg': 10, 'list_of_B': [{'b_arg': 5, 'list_of_A': [{'a': 100, 'b': 93}, {'a': 82, 'b': 52}, {'a': 39, 'b': 63}, {'a': 24, 'b': 94}, {'a': 40, 'b': 95}]}, {'b_arg': 5, 'list_of_A': [{'a': 100, 'b': 93}, {'a': 82, 'b': 52}, {'a': 39, 'b': 63}, {'a': 24, 'b': 94}, {'a': 40, 'b': 95}]}, {'b_arg': 5, 'list_of_A': [{'a': 100, 'b': 93}, {'a': 82, 'b': 52}, {'a': 39, 'b': 63}, {'a': 24, 'b': 94}, {'a': 40, 'b': 95}]}]}
quamrana
  • 37,849
  • 12
  • 53
  • 71
0

Your core logic is correct.
The issue however is that your list_of_A, list_of_B and c variables point to your class, while what interests you the most is the out_dict() method of that class.
Simple doing something like

from random import randint
class A:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def out_dict(self):
        return self.__dict__

class B:
    def __init__(self, B_a, list_of_A):
        self.b_arg = B_a
        self.list_of_A = list_of_A
    def out_dict(self):
        return self.__dict__

class C:
    def __init__(self, C_a, list_of_B):
        self.c_arg = C_a
        self.list_of_B = list_of_B
    def out_dict(self):
        return self.__dict__

list_of_A = [A(randint(0,100), randint(0,100)).out_dict() for _ in range(5)]
#This                                         ^
list_of_B = [B(5, list_of_A).out_dict() for _ in range(3)]
#Solves                     ^
c = C(10, list_of_B).out_dict()
#It                 ^
print(c)

Fixes the issue

Kasem Alsharaa
  • 892
  • 1
  • 6
  • 15