Search code examples
jsonpython-3.xsimplejson

json: nesting outputs the correct way


I'm using json to output a bunch of classes.

The problem that i am trying to solve is what is the best way to output json for a nested class. The following simple example highlights the problem.

# python 3.x
import json

class Class1:
    def __init__(self):

        self.a = 'this'
        self.b = 33

    def toJSON(self):
        return json.dumps({'a': self.a,
                           'b': self.b},
                            sort_keys=False, indent=2, separators=(',', ': '))

class Class2:
    def __init__(self):
        self.x = 'hello'
        self.y = Class1()
        self.z = 'world'

    def toJSON(self):
        return json.dumps({'x': self.x,
                           'y': self.y.toJSON(),
                           'z': self.z},
                            sort_keys=False, indent=2, separators=(',', ': '))


if __name__ == '__main__':
    a = Class2()

print(a.toJSON())

This is the output I'm getting. Which contains control characters

  {
    "x": "hello",
    "y": "{\n  \"a\": \"this\",\n  \"b\": 33\n}",
    "z": "world"
  }

This is the output I want would look something like this

{
  "x":"hello",
  "y":{
       "a":"this",
       "b":33
      },
  "z":"world"
}

Any assistance would be greatly appreciated.


Solution

  • I think you could implement cls encoder and then pass cls to json.dumps function like the following example.

    import json
    
    class Class1:
        def __init__(self):
            self.a = 'this'
            self.b = 33
    
    class Class2:
        def __init__(self):
            self.x = 'hello'
            self.y = Class1()
            self.z = 'world'
    
    
    class ComplexEncoder(json.JSONEncoder):
        def default(self, obj):
            if hasattr(obj, '__dict__'):
                return obj.__dict__
            else:
                return json.JSONEncoder.default(self, obj)
    
    if __name__ == '__main__':
        a = Class2()
    
    print(json.dumps(a, cls=ComplexEncoder, sort_keys=False, indent=2, separators=(',', ': ')))