diff --git a/linode_api4/objects/image.py b/linode_api4/objects/image.py index c9ac43863..931ed4a31 100644 --- a/linode_api4/objects/image.py +++ b/linode_api4/objects/image.py @@ -24,6 +24,8 @@ class ImageRegion(JSONObject): The region and status of an image replica. """ + include_none_values = True + region: str = "" status: Optional[ReplicationStatus] = None diff --git a/linode_api4/objects/lke.py b/linode_api4/objects/lke.py index b0e628196..1c2ed3c1a 100644 --- a/linode_api4/objects/lke.py +++ b/linode_api4/objects/lke.py @@ -55,6 +55,8 @@ class LKENodePoolTaint(JSONObject): applied to a node pool. """ + include_none_values = True + key: Optional[str] = None value: Optional[str] = None effect: Optional[str] = None @@ -103,6 +105,8 @@ class LKEClusterControlPlaneACLAddresses(JSONObject): to access an LKE cluster's control plane. """ + include_none_values = True + ipv4: Optional[List[str]] = None ipv6: Optional[List[str]] = None @@ -116,6 +120,8 @@ class LKEClusterControlPlaneACL(JSONObject): NOTE: Control Plane ACLs may not currently be available to all users. """ + include_none_values = True + enabled: bool = False addresses: Optional[LKEClusterControlPlaneACLAddresses] = None diff --git a/linode_api4/objects/serializable.py b/linode_api4/objects/serializable.py index b0e7a2503..fea682f43 100644 --- a/linode_api4/objects/serializable.py +++ b/linode_api4/objects/serializable.py @@ -58,6 +58,12 @@ class JSONObject(metaclass=JSONFilterableMetaclass): ) """ + include_none_values: ClassVar[bool] = False + """ + If true, all None values for this class will be explicitly included in + the serialized output for instance of this class. + """ + always_include: ClassVar[Set[str]] = {} """ A set of keys corresponding to fields that should always be @@ -169,7 +175,7 @@ def should_include(key: str, value: Any) -> bool: Returns whether the given key/value pair should be included in the resulting dict. """ - if key in cls.always_include: + if cls.include_none_values or key in cls.always_include: return True hint = type_hints.get(key) diff --git a/test/unit/objects/serializable_test.py b/test/unit/objects/serializable_test.py index 579417e1c..a15f108b4 100644 --- a/test/unit/objects/serializable_test.py +++ b/test/unit/objects/serializable_test.py @@ -26,3 +26,24 @@ class Foo(JSONObject): assert foo["foo"] == "test" assert foo["bar"] == "test2" assert foo["baz"] == "test3" + + def test_serialize_optional_include_None(self): + @dataclass + class Foo(JSONObject): + include_none_values = True + + foo: Optional[str] = None + bar: Optional[str] = None + baz: str = None + + foo = Foo().dict + + assert foo["foo"] is None + assert foo["bar"] is None + assert foo["baz"] is None + + foo = Foo(foo="test", bar="test2", baz="test3").dict + + assert foo["foo"] == "test" + assert foo["bar"] == "test2" + assert foo["baz"] == "test3"