Skip to content

Fail to parse a field that could a string or an object #187

@anobli

Description

@anobli

For context, I am trying to parse an existing yaml config format defined and used by ESPHome (a tool to build fimware for home automation devices).
In the format, sometime, a field could have different type of value. As example, the pin field could a int, a string (gpioxx) or for advanced use case, an object.

Here is a more detailed example:

from __future__ import annotations

from dataclasses import dataclass

from dataclass_wizard import JSONWizard


@dataclass
class Data(JSONWizard):
    """
    Data dataclass

    """
    switch: list[Switch]


@dataclass
class Switch:
    """
    Switch dataclass

    """
    platform: str
    pin: str | Pin | int
    name: str
    id: str


@dataclass
class Pin:
    """
    Pin dataclass

    """
    number: str
    inverted: bool

input_data = '{"switch": [{"platform": "gpio", "pin": "GPIOXX", "name": "Relay #1", "id": "relay1"}, {"platform": "gpio", "pin": {"number": "GPIO14", "inverted": true}, "name": "Relay #2", "id": "relay2"}, {"platform": "gpio", "pin": 15, "name": "Relay #3", "id": "relay3"}]}'
data = Data.from_json(input_data)

Unfortunately, this doesn't work. I get the following error:

dataclass_wizard.errors.ParseError: Failure parsing field `pin` in class `Switch`. Expected a type [<class 'str'>, <class 'int'>], got dict.
  value: {'number': 'GPIO14', 'inverted': True}
  error: Object was not in any of Union types
  tag_key: '__tag__'
  json_object: '{"platform": "gpio", "pin": {"number": "GPIO14", "inverted": true}, "name": "Relay #2", "id": "relay2"}'

As a workaround, I am going to use dict instead of Pin and do a second pass to parse the value of pin field if this is a dict.
But, it would be great if dataclass-wizard could handle it for me (at least, to check the schema).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions