diff --git a/miio/miot_models.py b/miio/miot_models.py index f70e4c9c8..53592a5ba 100644 --- a/miio/miot_models.py +++ b/miio/miot_models.py @@ -159,6 +159,15 @@ class MiotAction(MiotBaseModel): inputs: Any = Field(alias="in") outputs: Any = Field(alias="out") + @root_validator(pre=True) + def default_null_to_empty(cls, values): + """Coerce null values for in&out to empty lists.""" + if values["in"] is None: + values["in"] = [] + if values["out"] is None: + values["out"] = [] + return values + def fill_from_parent(self, service: "MiotService"): """Overridden to convert inputs and outputs to property references.""" super().fill_from_parent(service) diff --git a/miio/tests/test_miot_models.py b/miio/tests/test_miot_models.py index eaf8d9e4f..32afb76aa 100644 --- a/miio/tests/test_miot_models.py +++ b/miio/tests/test_miot_models.py @@ -138,6 +138,26 @@ def test_action(): assert act.plain_name == "dummy-action" +def test_action_with_nulls(): + """Test that actions with null ins and outs are parsed correctly.""" + simple_action = """\ + { + "iid": 1, + "type": "urn:miot-spec-v2:action:dummy-action:0000001:dummy:1", + "description": "Description", + "in": null, + "out": null + }""" + act = MiotAction.parse_raw(simple_action) + assert act.aiid == 1 + assert act.urn.type == "action" + assert act.description == "Description" + assert act.inputs == [] + assert act.outputs == [] + + assert act.plain_name == "dummy-action" + + @pytest.mark.parametrize( ("urn_string", "unexpected"), [