Initialize nested classes from JSON in Python?
<p>When writing APIs I often need to initialize classes from nested JSONs like this</p>

<pre><code># When my API receives such a ...
n_json = {"nested1": {"nested2" : { "nested3" : "..." }}}

# .. I need to instantiate a proper object out of it ...
nested1 = Nested1.from_json(json.loads(n_json))

# ... so I can later use the instance in OOP style.
nested1.nested2.run_an_intance_method()
</code></pre>

<p>In my code this results in cascades of</p>

<pre><code>class Nested1:
    @classmethod
    def from_json(json):
        self.nested2=Nested2.from_json(json.nested2)
</code></pre>

<p>With every layer of nesting this gets more repetetive and error prone. Any clever way to do this?</p>

<p>This is how you can create a nested object from JSON (similarly to how PHP does that). To create object tree from JSON (rather, parsed JSON, which is just a Python structure), write the following class:</p>

<pre><code>class Nested:
    def __new__(cls, structure):
        self = super(Nested, cls).__new__(cls)
        if type(structure) is dict:
            self.__dict__ = {key: Nested(structure[key]) for key in structure}
        elif type(structure) is list:
            self = [Nested(item) for item in structure]
        else:
            self = structure
        return self
</code></pre>

<p>and call it from your parsed JSON. For example:</p>

<pre><code>import json

s = json.dumps({'a': 1, 'b': {'c': [1, 2, {'d': 3}], 'e': {'f': 'g'}}})

result = Nested(json.loads(s))

print(result.a)  #  1

print(result.b.c) # [1, 2, &lt;__main__.Nested object at 0x00000297A983D828&gt;]

print(result.b.c[0]) # 1

print(result.b.c[2].d) # 3
</code></pre>

<hr>

<p>Here is what is how the class works:</p>

<ol>
<li><p><code>__new__</code> is invoked before anything else. Here we construct an instance of an object (empty)</p></li>
<li><p>If new is list, we replace self with list of nested objects, so that <code>Nested({'a': [1, 2, 3]).a</code> is equal to <code>[Nested(1), Nested(2), Nested(3)]</code> (which also equals to just <code>[1, 2, 3]</code>, see number 4)</p></li>
<li><p>If new is dict, for each key we create a property with the same name and assign <code>Nested(dict[key])</code> to it.</p></li>
<li><p>If any other type, just assign value to self (replace <code>self</code> with value) so that <code>Nested({'a': ['b', 'c', 'd']}).a[0]</code> equals <code>'b'</code>, not <code>Nested(..)</code></p></li>
</ol>

python json api web-applications