You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JsonObject subclasses dict but when wrapping arrays or scalars, it returns early from __init__ without calling super().__init__(). This leaves the dict parent empty, causing standard Python operations to silently return wrong results.
Reproduction
fromgoogle.cloud.spanner_v1importJsonObjectimportjsonval=JsonObject([{"id": "m1", "content": "hello"}])
print(isinstance(val, dict)) # True — it IS a dict subclassprint(len(val)) # 0 — expected 1print(bool(val)) # False — expected Trueprint(list(val)) # [] — expected the list contentsprint(json.dumps(val)) # "{}" — expected the JSON arrayprint(val.serialize()) # '[{"content":"hello","id":"m1"}]' — correct
Root cause
In data_types.py, the array and scalar paths return early without initializing the dict:
def__init__(self, *args, **kwargs):
self._is_array=len(args) andisinstance(args[0], (list, tuple))
ifself._is_array:
self._array_value=args[0]
return# ← dict parent never initializedifself._is_scalar_value:
self._simple_value=args[0]
return# ← same issue
The dict path (JSON objects) works correctly because it falls through to super().__init__().
Impact
Any code that receives a JsonObject wrapping an array and uses standard Python operations (len(), bool(), for x in val, val or default, json.dumps()) gets silently wrong results. This is particularly dangerous because isinstance(val, dict) returns True, so type checks pass but the object doesn't behave like one.
The .serialize() method works correctly for all variants because it reads from the internal _array_value/_simple_value attributes directly.
Suggested fix
Override __len__, __bool__, __iter__, and __getitem__ to delegate to the internal storage for array/scalar variants. Or stop subclassing dict since the array/scalar variants don't use it.
Version
Tested on 3.55.0, confirmed identical source in 3.61.0 (latest).
Activity
fix: JsonObject array/scalar variants now implement standard dict pro…
chalmerlowe commentedon Mar 2, 2026
This issue was moved from the following repo as part of the monorepo migration: googleapis/python-spanner
fix: JsonObject array/scalar variants now implement standard dict pro…
waiho-gumloop commentedon Apr 1, 2026
Fix re-submitted for the monorepo: #16496
fix(spanner): implement dict protocol and nested unwrapping for JsonO…
fix(spanner): implement dict protocol and nested unwrapping for JsonO…
chore: release main (#17832)