Repository: yukinarit/pyserde

Issue:
Unable to deserialize null value for type `Optional[UUID] = None`
Hi, pyserde seems to mishandle this very specific corner case.

Minimum example:

```python
from serde import serde, to_dict, from_dict
from uuid import UUID
from typing import Optional
from dataclasses import dataclass

@serde
@dataclass
class NameId:
    name: str
    id: Optional[UUID] = None  # <====== UUID and `None` here is the problem 

x = NameId("Fred", None)
j = to_dict(x)
y = from_dict(NameId, j)
```

Everything before the last line works fine.  The last line gives the error below.

If I remove the default for `id` (i.e., remove `= None`), it works fine.
If I change the type of `id` to `Optional[int] = None`, it works fine.

So it's specific to `Optional[UUID] = None`.

From the error, it seems like it's trying to parse `None` as a `UUID`.

Here's the error:
```
Traceback (most recent call last):
  File "/Users/kevin.squire/Library/Caches/pypoetry/virtualenvs/pyserde-Y2i1skxI-py3.10/lib/python3.10/site-packages/serde/de.py", line 338, in from_obj
    res = serde_scope.funcs[func_name](c, maybe_generic=maybe_generic, data=o, reuse_instances=reuse_instances)
  File "<string>", line 13, in from_dict
  File "/Users/kevin.squire/.pyenv/versions/3.10.5_x86/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/uuid.py", line 171, in __init__
    raise TypeError('one of the hex, bytes, bytes_le, fields, '
TypeError: one of the hex, bytes, bytes_le, fields, or int arguments must be given

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/kevin.squire/tmp/pyserde/tmp/test.py", line 15, in <module>
    y = from_dict(NameId, j)
  File "/Users/kevin.squire/Library/Caches/pypoetry/virtualenvs/pyserde-Y2i1skxI-py3.10/lib/python3.10/site-packages/serde/de.py", line 414, in from_dict
    return from_obj(cls, o, named=True, reuse_instances=reuse_instances)
  File "/Users/kevin.squire/Library/Caches/pypoetry/virtualenvs/pyserde-Y2i1skxI-py3.10/lib/python3.10/site-packages/serde/de.py", line 391, in from_obj
    raise SerdeError(e)
serde.compat.SerdeError: one of the hex, bytes, bytes_le, fields, or int arguments must be given
```

Discussion:

Patch:
diff --git a/serde/de.py b/serde/de.py
index 240df8b..a88a2e7 100644
--- a/serde/de.py
+++ b/serde/de.py
@@ -648,14 +648,11 @@ class Renderer:
 if data.get("f") is not None else None'
         """
         value = arg[0]
-        if has_default(arg):
-            return self.render(value)
+        if arg.iterbased:
+            exists = f'{arg.data} is not None'
         else:
-            if arg.iterbased:
-                exists = f'{arg.data} is not None'
-            else:
-                exists = f'{arg.datavar}.get("{arg.conv_name()}") is not None'
-            return f'({self.render(value)}) if {exists} else None'
+            exists = f'{arg.datavar}.get("{arg.conv_name()}") is not None'
+        return f'({self.render(value)}) if {exists} else None'
 
     def list(self, arg: DeField) -> str:
         """


Test patch:
diff --git a/tests/test_union.py b/tests/test_union.py
index be7317a..e6fa792 100644
--- a/tests/test_union.py
+++ b/tests/test_union.py
@@ -225,6 +225,29 @@ def test_optional_union_with_complex_types():
     assert a_none == from_dict(A, to_dict(a_none, reuse_instances=True), reuse_instances=True)
 
 
+def test_optional_complex_type_with_default():
+    for T, default in [
+        (IPv4Address, IPv4Address("127.0.0.1")),
+        (UUID, UUID("9c244009-c60d-452b-a378-b8afdc0c2d90")),
+    ]:
+
+        @serde
+        class A:
+            id: Optional[T] = None
+
+        a = A(default)
+        assert a == from_dict(A, to_dict(a, reuse_instances=False), reuse_instances=False)
+        assert a == from_dict(A, to_dict(a, reuse_instances=True), reuse_instances=True)
+
+        a_none = A(None)
+        assert a_none == from_dict(A, to_dict(a_none, reuse_instances=False), reuse_instances=False)
+        assert a_none == from_dict(A, to_dict(a_none, reuse_instances=True), reuse_instances=True)
+
+        a_default = A()
+        assert a_default == from_dict(A, to_dict(a_default, reuse_instances=False), reuse_instances=False)
+        assert a_default == from_dict(A, to_dict(a_default, reuse_instances=True), reuse_instances=True)
+
+
 def test_union_with_complex_types_in_containers():
     @serde
     class A: