Skip to content

Commit acbf067

Browse files
vistartclaude
andcommitted
fix(test): register PostgresJSONBAdapter for JsonUser JSON fields
psycopg3 automatically deserializes JSONB columns to Python dict/list, but JsonUser's JSON fields are defined as Optional[str] in the testsuite. Without a type adapter, Pydantic validation fails when receiving dict instead of str from the database. Register PostgresJSONBAdapter for all JSON fields in setup_json_user_fixtures and setup_async_json_user_fixtures. The adapter's from_database() method converts dict/list back to JSON string when target_type is str. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 0fe59cb commit acbf067

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

‎tests/providers/query.py‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,20 @@ def setup_blog_fixtures(self, scenario_name: str) -> Tuple[Type[ActiveRecord], T
220220
return self._setup_multiple_models(models_and_tables, scenario_name)
221221

222222
def setup_json_user_fixtures(self, scenario_name: str) -> Tuple[Type[ActiveRecord], ...]:
223-
"""Sets up the database for the JSON user model."""
223+
"""Sets up the database for the JSON user model.
224+
225+
Registers PostgresJSONBAdapter for JSON fields so that psycopg3's
226+
automatic JSONB deserialization (dict/list) is converted back to str
227+
before Pydantic validation, matching the model's Optional[str] type.
228+
"""
229+
from rhosocial.activerecord.backend.impl.postgres.adapters import PostgresJSONBAdapter
230+
231+
jsonb_adapter = PostgresJSONBAdapter()
232+
json_fields = ["settings", "tags", "profile", "roles", "scores", "subscription", "preferences"]
233+
for field_name in json_fields:
234+
if field_name not in JsonUser.__field_adapters__:
235+
JsonUser.__field_adapters__[field_name] = (jsonb_adapter, str)
236+
224237
models_and_tables = [
225238
(JsonUser, "json_users"),
226239
]
@@ -289,8 +302,21 @@ async def setup_async_blog_fixtures(self, scenario_name: str) -> Tuple[Type[Acti
289302
], scenario_name)
290303

291304
async def setup_async_json_user_fixtures(self, scenario_name: str) -> Tuple[Type[ActiveRecord], ...]:
292-
"""Sets up the database for the async JSON user model."""
305+
"""Sets up the database for the async JSON user model.
306+
307+
Registers PostgresJSONBAdapter for JSON fields so that psycopg3's
308+
automatic JSONB deserialization (dict/list) is converted back to str
309+
before Pydantic validation, matching the model's Optional[str] type.
310+
"""
293311
from rhosocial.activerecord.testsuite.feature.query.fixtures.async_json_models import AsyncJsonUser
312+
from rhosocial.activerecord.backend.impl.postgres.adapters import PostgresJSONBAdapter
313+
314+
jsonb_adapter = PostgresJSONBAdapter()
315+
json_fields = ["settings", "tags", "profile", "roles", "scores", "subscription", "preferences"]
316+
for field_name in json_fields:
317+
if field_name not in AsyncJsonUser.__field_adapters__:
318+
AsyncJsonUser.__field_adapters__[field_name] = (jsonb_adapter, str)
319+
294320
return await self._setup_multiple_models_async([
295321
(AsyncJsonUser, "json_users"),
296322
], scenario_name)

0 commit comments

Comments
 (0)