22

I want to parse json and save it in dataclasses to emulate DTO. Currently, I ahve to manually pass all the json fields to dataclass. I wanted to know is there a way I can do it by just adding the json parsed dict ie. "dejlog" to dataclass and all the fields are populated automactically.

from dataclasses import dataclass,  asdict


@dataclass
class Dejlog(Dataclass):
    PK: str
    SK: str
    eventtype: str
    result: str
    type: str
    status: str

def lambda_handler(event, context):
    try:
        dejlog = json.loads(event['body'])

        x = Dejlog(dejlog['PK'])

        print(x)

        print(x.PK)
4
  • import json has all the functions you need Commented Apr 26, 2022 at 11:51
  • load json to dict and then intérnable unpack into le dataclass instance Commented Apr 26, 2022 at 11:52
  • If dejlog contains the expected keys, what you want is x = Dejlog(**dejlog). Commented Apr 26, 2022 at 11:59
  • @SergeBallesta Yes thank you but If there is a new (unexpected ) key added to json then unpacking will fail. Any way to overcome it. Also if some fields in json contain list or object, and in data class I have mentioned str. How to handle it. Commented Apr 26, 2022 at 13:18

4 Answers 4

19

As mentioned in other comments you can use the in-built json lib as so:

from dataclasses import dataclass
import json

json_data_str = """
{
   "PK" : "Foo",
   "SK" : "Bar",
   "eventtype" : "blah",
   "result" : "something",
   "type" : "badger",
   "status" : "active"
}
"""

@dataclass
class Dejlog:
    PK: str
    SK: str
    eventtype: str
    result: str
    type: str
    status: str


json_obj = json.loads(json_data_str)
dejlogInstance = Dejlog(**json_obj)

print(dejlogInstance)
Sign up to request clarification or add additional context in comments.

1 Comment

Note that this is shallow: it won't work if your dataclass contains other dataclasses. For that, see stackoverflow.com/q/69059290/388951.
11

Unpacking works as long as you don't have any unexpected keys in the json object, otherwise you'll get a TypeError. An alternative is to use a classmethod to create instances of the dataclass. Building on the earlier example:

json_data_str = """
{
   "PK" : "Foo",
   "SK" : "Bar",
   "eventtype" : "blah",
   "result" : "something",
   "type" : "badger",
   "status" : "active",
   "unexpected": "I did not expect this"
}
"""

@dataclass
class Dejlog:
    PK: str
    SK: str
    eventtype: str
    result: str
    type: str
    status: str
    
    @classmethod
    def from_dict(cls, data):
        return cls(
            PK = data.get('PK'),
            SK = data.get('SK'),
            eventtype = data.get('eventtype'),
            result=data.get('result'),
            type=data.get('type'),
            status=data.get('status')
        )

json_obj = json.loads(json_data_str)
dejlogInstance = Dejlog.from_dict(json_obj)

Comments

1

Here is a simple classmethod that handles missing or extra keys. Building on an earlier answer:

import dataclasses
import json

json_data_str = """
{
   "PK" : "Foo",
   "SK" : "Bar",
   "eventtype" : "blah",
   "result" : "something",
   "type" : "badger",
   "status" : "active",
   "unexpected": "I did not expect this"
}
"""

@dataclasses.dataclass
class Dejlog:
    PK: str
    SK: str
    eventtype: str
    result: str
    type: str
    status: str

    @classmethod
    def from_dict(cls, data):
        return cls(
            *[data.get(fld.name)
              for fld in dataclasses.fields(Dejlog)]
        )

json_obj = json.loads(json_data_str)
dejlogInstance = Dejlog.from_dict(json_obj)

Comments

0

You can load json to your dataclass object using hook_object param like this:

import json
from dataclasses import dataclass


@dataclass
class Dejlog:
    PK: str
    SK: str
    eventtype: str
    result: str
    type: str
    status: str


my_obj = json.loads(
    open('/path/to/file', 'r').read(),
    object_hook=lambda args: Dejlog(**args)
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.