Repository: yukinarit/pyserde (python)

Issue:
`alias` on `Optional` field breaks deserialization
Hi there,

Using the latest version (0.12.2), this example consistently deserializes `Foo.a` to `None`:
```py
@serde
@dataclass
class Foo:
    a: Optional[int] = field(alias=["b"])

x = from_json(Foo, '{"b": 1}')
assert x.a == 1 💥
```

Pull request:
Fix alias of optional type
Closes #429 

Patch:
diff --git a/serde/de.py b/serde/de.py
index be905d8..7752fd5 100644
--- a/serde/de.py
+++ b/serde/de.py
@@ -123,13 +123,18 @@ def default_deserializer(_cls: Type[Any], obj: Any) -> Any:
     """
 
 
-def _get_by_aliases(d: Dict[str, str], aliases: List[str]) -> str:
+def _get_by_aliases(
+    d: Dict[str, str], aliases: List[str], raise_error: bool = True
+) -> Optional[str]:
     if not aliases:
-        raise KeyError("Tried all aliases, but key not found")
+        if raise_error:
+            raise KeyError("Tried all aliases, but key not found")
+        else:
+            return None
     if aliases[0] in d:
         return d[aliases[0]]
     else:
-        return _get_by_aliases(d, aliases[1:])
+        return _get_by_aliases(d, aliases[1:], raise_error=raise_error)
 
 
 def _exists_by_aliases(d: Dict[str, str], aliases: List[str]) -> bool:
@@ -804,7 +809,13 @@ reuse_instances=reuse_instances)) if data.get("f") is not None else None'
         if arg.iterbased:
             exists = f"{arg.data} is not None"
         else:
-            exists = f'{arg.datavar}.get("{arg.conv_name()}") is not None'
+            name = arg.conv_name()
+            if arg.alias:
+                aliases = (f'"{s}"' for s in [name, *arg.alias])
+                get = f"_get_by_aliases(data, [{','.join(aliases)}], raise_error=False)"
+            else:
+                get = f'{arg.datavar}.get("{name}")'
+            exists = f"{get} is not None"
         return f"({self.render(value_arg)}) if {exists} else None"
 
     def list(self, arg: DeField[Any]) -> str:


Test patch:
diff --git a/tests/test_basics.py b/tests/test_basics.py
index 41b6769..d3efd01 100644
--- a/tests/test_basics.py
+++ b/tests/test_basics.py
@@ -573,6 +573,15 @@ def test_default_and_alias():
     assert ff.a == 2
 
 
+def test_optional_and_alias():
+    @serde.serde
+    class Foo:
+        a: Optional[int] = serde.field(alias=["b"])
+
+    assert Foo(1) == serde.json.from_json(Foo, '{"b":1}')
+    assert Foo(None) == serde.json.from_json(Foo, '{"c":1}')
+
+
 def test_default_and_rename():
     @serde.serde
     class Foo: