Skip to content

Commit d356168

Browse files
authored
Merge pull request #430 from yukinarit/fix-alias-optional
Fix alias of optional type
2 parents 2855b6b + f8f33df commit d356168

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

serde/de.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,18 @@ def default_deserializer(_cls: Type[Any], obj: Any) -> Any:
123123
"""
124124

125125

126-
def _get_by_aliases(d: Dict[str, str], aliases: List[str]) -> str:
126+
def _get_by_aliases(
127+
d: Dict[str, str], aliases: List[str], raise_error: bool = True
128+
) -> Optional[str]:
127129
if not aliases:
128-
raise KeyError("Tried all aliases, but key not found")
130+
if raise_error:
131+
raise KeyError("Tried all aliases, but key not found")
132+
else:
133+
return None
129134
if aliases[0] in d:
130135
return d[aliases[0]]
131136
else:
132-
return _get_by_aliases(d, aliases[1:])
137+
return _get_by_aliases(d, aliases[1:], raise_error=raise_error)
133138

134139

135140
def _exists_by_aliases(d: Dict[str, str], aliases: List[str]) -> bool:
@@ -804,7 +809,13 @@ def opt(self, arg: DeField[Any]) -> str:
804809
if arg.iterbased:
805810
exists = f"{arg.data} is not None"
806811
else:
807-
exists = f'{arg.datavar}.get("{arg.conv_name()}") is not None'
812+
name = arg.conv_name()
813+
if arg.alias:
814+
aliases = (f'"{s}"' for s in [name, *arg.alias])
815+
get = f"_get_by_aliases(data, [{','.join(aliases)}], raise_error=False)"
816+
else:
817+
get = f'{arg.datavar}.get("{name}")'
818+
exists = f"{get} is not None"
808819
return f"({self.render(value_arg)}) if {exists} else None"
809820

810821
def list(self, arg: DeField[Any]) -> str:

tests/test_basics.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,15 @@ class Foo:
573573
assert ff.a == 2
574574

575575

576+
def test_optional_and_alias():
577+
@serde.serde
578+
class Foo:
579+
a: Optional[int] = serde.field(alias=["b"])
580+
581+
assert Foo(1) == serde.json.from_json(Foo, '{"b":1}')
582+
assert Foo(None) == serde.json.from_json(Foo, '{"c":1}')
583+
584+
576585
def test_default_and_rename():
577586
@serde.serde
578587
class Foo:

0 commit comments

Comments
 (0)