Tip #117: Quick Reference: Deserialize JSON into Python object

The goal of this article is to provide an example to create a custom Python object out of a complex JSON structure. The reason for using a custom Python object is to account for additional processing/formatting from an API service that could evolve over time and provides a better interface. Also using a custom Python object provides better control for decoupling and information hiding.

With the example provided, I’m choosing to use a JSON structure that has a mix of strings, structures and arrays which better represent more common JSON message structures.

Sample JSON (testdata2.json)

{
  "name": "Bob",
  "arr1": [
    {
      "PropA": "A1",
      "PropB": "B1"
    },
    {
      "PropA": "A2",
      "PropB": "B2"
    }
  ],
  "totalCount": 1,
  "props": {
    "field1": "a",
    "field2": "b",
    "field3": "c"
  }
}
# sample.py

class Arry1Rec (object):
    def __init__(self, PropA: str, PropB: str):
        self.PropA = PropA
        self.PropB = PropB
    @classmethod
    def from_json(cls, data):
        return cls(**data)

class Propscls(object):
    def __init__(self, field1: str, field2: str, field3: str):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3
    @classmethod
    def from_json(cls, data):
        return cls(**data)

class Filecls(object):
    def __init__(self, name: str, arry1: List[Arry1Rec], totalCount: int, props: Propscls ):
        self.name = name
        self.totalCount = totalCount
        self.props = props
        self.data = data
        self.arry1=arry1
    @classmethod
    def from_json(cls, data):
        name = data["name"]
        arry1 = list(map(Arry1Rec.from_json, data["arr1"]))
        totalCount = data["totalCount"]
        props = Propscls.from_json(data=data["props"])
        return cls(name=name, arry1=arry1, totalCount=totalCount, props=props)

with open('./sampleData/testdata2.json', encoding='utf-8-sig', errors='ignore') as infile2:
    jsonDataComplex1 = json.load(infile2, strict=False)

decoded_file = Filecls.from_json(jsonDataComplex1)

print('test: decoded_file.props.field1')
print(decoded_file.props.field3)