7

I stumbled upon a problem, when I was working on my ETL pipeline. I am using dataclasses dataclass to parse JSON objects. One of the keywords of the JSON object is a reserved keyword. Is there a way around this:

from dataclasses import dataclass
import jsons

out = {"yield": 0.21}

@dataclass
class PriceObj:
    asOfDate: str
    price: float
    yield: float

jsons.load(out, PriceObj)

This will obviously fail because yield is reserved. Looking at the dataclasses field definition, there doesn't seem to be anything in there that can help.

Go, allows one to define the name of the JSON field, wonder if there is such a feature in the dataclass?

Naz
  • 2,012
  • 1
  • 21
  • 45
  • I have a solution, replace all the Python reserved words in the JSON object's keys before sending it to load lol – Naz Feb 05 '20 at 11:12
  • Try this answer https://stackoverflow.com/a/49911616/7194553 (spoiler: it's not trivial, you'll probably want to use a different pattern) – repoleved Feb 05 '20 at 11:13

2 Answers2

7

You can decode / encode using a different name with the dataclasses_json lib, from their docs:

from dataclasses import dataclass, field

from dataclasses_json import config, dataclass_json

@dataclass_json
@dataclass
class Person:
    given_name: str = field(metadata=config(field_name="overriddenGivenName"))

Person(given_name="Alice")  # Person('Alice')
Person.from_json('{"overriddenGivenName": "Alice"}')  # Person('Alice')
Person('Alice').to_json()  # {"overriddenGivenName": "Alice"}
So S
  • 581
  • 1
  • 7
  • 20
Naz
  • 2,012
  • 1
  • 21
  • 45
  • `dataclasses_json` is an incredibly useful lib that allows you to do many more cool things. For example, it gives you hook access to the decoder / encoder methods per dataclass field! – Naz Feb 06 '20 at 09:49
0

I found next solution for my purposes.

@dataclass
class ExampleClass:
    def __post_init__(self):
        self.__setattr__("class", self.class_)
        self.__delattr__("class_") 

    class_: str

It requires to set init value in class_ attribute. Also you can't directly use this attribute like example_class_instance.class, workaround is example_class_instance.__getattribute__("class"). And the dataclass has broken repr, can be avoided by changing decorator to dataclass(repr=False)