Skip to content

Error deserializing numeric members of a Union if followed by a collection #74

@NiklasRosenstein

Description

@NiklasRosenstein

To reproduce:

# /// script
# requires-python = ">=3.10"
# dependencies = ["databind"]
# ///

from typing import Any
from databind.json import load


JsonValue = dict[str, Any] | list[Any] | int | float | str | bool | None

print(load({}, JsonValue))
print(load([], JsonValue))
# print(load(42, JsonValue))  # TypeError: 'int' object is not iterable
# print(load(42.0, JsonValue))  # TypeError: 'float' object is not iterable
print(load("foo", JsonValue))
# print(load(True, JsonValue))  # TypeError: 'bool' object is not iterable
print(load(None, JsonValue))

Run with uv run --isolated script.py. The full relevant traceback is (the same for each of these):

...
  File "/home/niklas/.cache/uv/archive-v0/cHLqqCakBDH2r05n1gcZZ/lib/python3.13/site-packages/databind/core/context.py", line 123, in convert
    return self.convert_func(self)
           ~~~~~~~~~~~~~~~~~^^^^^^
  File "/home/niklas/.cache/uv/archive-v0/cHLqqCakBDH2r05n1gcZZ/lib/python3.13/site-packages/databind/core/converter.py", line 84, in convert
    return converter.convert(ctx)
           ~~~~~~~~~~~~~~~~~^^^^^
  File "/home/niklas/.cache/uv/archive-v0/cHLqqCakBDH2r05n1gcZZ/lib/python3.13/site-packages/databind/json/converters.py", line 148, in convert
    for idx, (val, item_type) in enumerate(zip(ctx.value, item_types_iterator))
                                           ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'bool' object is not iterable

A workaround is to move the numeric types to the front of the union:

-JsonValue = dict[str, Any] | list[Any] | int | float | str | bool | None
+JsonValue = int | float | bool | dict[str, Any] | list[Any] | str | None

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions