Repository: yukinarit/pyserde

Issue:
serde.compat.SerdeError: Can not serialize with untagged union of dict[str, Any]
`0.12.3` on Python 3.11.4:

```py
from dataclasses import dataclass
from typing import Any

from serde import Untagged, field, serde
from serde.yaml import from_yaml, to_yaml


@dataclass
class FooWithString:
    foo: str

@dataclass
class BarWithDict:
    bar: dict[str, Any] # remove [str, Any] to fix

@serde(tagging=Untagged)
@dataclass
class Klass:
    foobars: list[FooWithString | BarWithDict]

good_yaml = """
foobars:
  - foo: string
  - bar:
      key: value
"""

if __name__ == '__main__':
    config = from_yaml(Klass, good_yaml)
    print(to_yaml(config))
```

```
serde.compat.SerdeError: Can not serialize BarWithDict(bar={'key': 'value'}) of type BarWithDict for Union[FooWithString, BarWithDict]
```

---

Weirdly the more trivial case `list[BarWithDict]` works fine, as does just `BarWithDict`.
It's something specifically caused by it being in an untagged union list 🤔 


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/yukinarit/pyserde/pull/441?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yukinarit) Report
All modified and coverable lines are covered by tests :white_check_mark:

| [Files](https://app.codecov.io/gh/yukinarit/pyserde/pull/441?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yukinarit) | Coverage Δ | |
|---|---|---|
| [serde/core.py](https://app.codecov.io/gh/yukinarit/pyserde/pull/441?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yukinarit#diff-c2VyZGUvY29yZS5weQ==) | `85.24% <100.00%> (+0.06%)` | :arrow_up: |


:loudspeaker: Thoughts on this report? [Let us know!](https://about.codecov.io/pull-request-comment-report/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=yukinarit)


Patch:
diff --git a/serde/core.py b/serde/core.py
index 63449e2..7668d81 100644
--- a/serde/core.py
+++ b/serde/core.py
@@ -44,6 +44,7 @@ from .compat import (
     is_list,
     is_literal,
     is_new_type_primitive,
+    is_any,
     is_opt,
     is_set,
     is_tuple,
@@ -382,6 +383,8 @@ def is_instance(obj: Any, typ: Any) -> bool:
             return isinstance(obj, inner)
         else:
             return False
+    elif is_any(typ):
+        return True
     elif typ is Ellipsis:
         return True
     else:


Test patch:
diff --git a/tests/test_union.py b/tests/test_union.py
index af02d6d..f482028 100644
--- a/tests/test_union.py
+++ b/tests/test_union.py
@@ -2,7 +2,7 @@ import logging
 import sys
 from dataclasses import dataclass
 from ipaddress import IPv4Address
-from typing import Dict, FrozenSet, Generic, List, NewType, Optional, Tuple, TypeVar, Union
+from typing import Dict, FrozenSet, Generic, List, NewType, Optional, Tuple, TypeVar, Union, Any
 from uuid import UUID
 
 import pytest
@@ -772,3 +772,21 @@ def test_union_frozenset_with_prim():
         a: Union[FrozenSet[int], int]
 
     assert to_dict(Foo(frozenset({1}))) == {"a": {1}}
+
+
+def test_union_with_any():
+    @dataclass
+    class FooWithString:
+        foo: str
+
+    @dataclass
+    class BarWithDict:
+        bar: Dict[str, Any]
+
+    @serde(tagging=Untagged)
+    @dataclass
+    class Class:
+        foobars: List[Union[FooWithString, BarWithDict]]
+
+    c = Class([FooWithString("string"), BarWithDict({"key": "value"})])
+    assert c == from_json(Class, to_json(c))