fix: JsonObject array/scalar variants now implement standard dict protocol by waiho-gumloop · Pull Request #16496 · googleapis/google-cloud-python

Description

JsonObject subclasses dict but when wrapping arrays or scalars, __init__ returns early without calling super().__init__(). This leaves the dict parent empty, causing len(), bool(), iter(), indexing, json.dumps(), and in to silently return wrong results -- while isinstance(obj, dict) returns True.

This has been present since the array support was added in Aug 2022 (googleapis/python-spanner#782).

What this PR does

Adds __len__, __bool__, __iter__, __getitem__, __contains__, and __eq__ overrides that delegate to the internal _array_value/_simple_value for non-dict variants. Dict variant behavior is unchanged (delegates to super()).

Before (broken)

val = JsonObject([{"id": "m1", "content": "hello"}])
isinstance(val, dict)  # True
len(val)               # 0  <-- wrong
bool(val)              # False  <-- wrong
list(val)              # []  <-- wrong
json.dumps(val)        # "{}"  <-- wrong

After (fixed)

val = JsonObject([{"id": "m1", "content": "hello"}])
isinstance(val, dict)  # True
len(val)               # 1  <-- correct
bool(val)              # True  <-- correct
list(val)              # [{"id": "m1", "content": "hello"}]  <-- correct
val[0]                 # {"id": "m1", "content": "hello"}  <-- correct

Tests

Added Test_JsonObject_dict_protocol test class covering len, bool, iter, getitem, contains, and eq for all four variants (array, dict, scalar, null). All tests pass.

Fixes #15870