Skip to content

Commit 1de6b67

Browse files
committed
no-mistakes(test): fix Python jsonb write codec for array-of-VO roundtrip
1 parent 883969a commit 1de6b67

1 file changed

Lines changed: 19 additions & 3 deletions

File tree

server/python/src/metaobjects/runtime/object_manager.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import datetime as _dt
2929
import decimal as _decimal
30+
import json as _json
3031
import uuid as _uuid
3132
from collections.abc import Iterable
3233
from typing import Any, Protocol
@@ -693,9 +694,24 @@ def _coerce_write_value(field: MetaField, value: Any) -> Any:
693694
is_tz = field.get_meta_attr(dbc.FIELD_ATTR_LOCAL_TIME) is not True # ADR-0039 resolving: @localTime may be inherited
694695
return _parse_datetime(str(value), tz_aware=is_tz)
695696

696-
# field.object (jsonb storage): a dict/list passes through — pg8000 binds it
697-
# to the jsonb column natively (no manual JSON.stringify, unlike node-pg).
698-
# A field.string pinned to a jsonb column behaves the same way.
697+
# field.object / field.map stored as a single jsonb column: serialize to a
698+
# JSON text string so pg8000 sends it as jsonb text (PG assignment-casts text
699+
# → jsonb). pg8000 binds a native *dict* to jsonb natively, but a native
700+
# *list* (array-of-VO, isArray:true) it adapts as a Postgres ARRAY literal
701+
# `{...,...}` which the JSONB column rejects with 22P02 'invalid input syntax
702+
# for type json' — so we cannot rely on driver magic for the list form.
703+
# Serializing both shapes to a JSON string is the explicit codec every other
704+
# port has (Java/Gson, C#/System.Text.Json, TS/JSON.stringify, Kotlin/Jackson)
705+
# and handles dict (single VO), list (array-of-VO), and [] uniformly.
706+
#
707+
# Scope: only jsonb-storage field.object/field.map. A *flattened* field.object
708+
# is expanded to separate scalar columns (never reaches here as the object
709+
# node) and must not be touched; a field.string pinned to a jsonb column via
710+
# @dbColumnType already carries a string value and is left alone above.
711+
if sub in (fc.FIELD_SUBTYPE_OBJECT, fc.FIELD_SUBTYPE_MAP):
712+
storage = field.get_meta_attr(fc.FIELD_ATTR_STORAGE) # ADR-0039 resolving
713+
if storage != "flattened": # None / "jsonb" / "subdocument" → single jsonb column
714+
return _json.dumps(value)
699715
# Everything else (string / int / long / double / float / boolean / enum)
700716
# is already the native type pg8000 binds directly.
701717
return value

0 commit comments

Comments
 (0)