|
27 | 27 |
|
28 | 28 | import datetime as _dt |
29 | 29 | import decimal as _decimal |
| 30 | +import json as _json |
30 | 31 | import uuid as _uuid |
31 | 32 | from collections.abc import Iterable |
32 | 33 | from typing import Any, Protocol |
@@ -693,9 +694,24 @@ def _coerce_write_value(field: MetaField, value: Any) -> Any: |
693 | 694 | is_tz = field.get_meta_attr(dbc.FIELD_ATTR_LOCAL_TIME) is not True # ADR-0039 resolving: @localTime may be inherited |
694 | 695 | return _parse_datetime(str(value), tz_aware=is_tz) |
695 | 696 |
|
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) |
699 | 715 | # Everything else (string / int / long / double / float / boolean / enum) |
700 | 716 | # is already the native type pg8000 binds directly. |
701 | 717 | return value |
|
0 commit comments