From 80634fe60465180a44f98ebb3c3a34ce3763baf8 Mon Sep 17 00:00:00 2001 From: Monte Hoover Date: Mon, 20 Jul 2026 19:04:55 -0400 Subject: [PATCH] Update class generation code to handle empty data that php-style serialization emits as []. (#7599) --- cli/openbb_cli/codegen/pydantic_gen.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cli/openbb_cli/codegen/pydantic_gen.py b/cli/openbb_cli/codegen/pydantic_gen.py index 767c48011cc..1550404f6fe 100644 --- a/cli/openbb_cli/codegen/pydantic_gen.py +++ b/cli/openbb_cli/codegen/pydantic_gen.py @@ -554,6 +554,7 @@ def generate_class( imports: set[str] = {"from pydantic import BaseModel, Field"} body_lines: list[str] = [] doc_fields: list[tuple[str, str, str | None, bool, Any, bool]] = [] + optional_object_fields: list[str] = [] for raw_name, prop_schema in properties.items(): safe_name, needs_alias = safe_field_name(raw_name) @@ -566,6 +567,8 @@ def generate_class( ) is_required = raw_name in required_set prop = prop_schema if isinstance(prop_schema, dict) else {} + if not is_required and (prop.get("type") == "object" or "properties" in prop): + optional_object_fields.append(safe_name) has_default = "default" in prop if not is_required and "None" not in annotation: annotation = f"{annotation} | None" @@ -603,6 +606,20 @@ def generate_class( if not body_lines: body_lines.append(" pass") + if optional_object_fields: + # PHP-style serializers emit [] where the schema declares an object + # (empty associative array quirk); [] is never a valid JSON-object value. + imports.add("from pydantic import field_validator") + imports.add("from typing import Any") + names = ", ".join(repr(n) for n in optional_object_fields) + body_lines.append( + f'\n @field_validator({names}, mode="before")\n' + " @classmethod\n" + " def _empty_list_to_none(cls, v: Any) -> Any:\n" + ' """Coerce `[]` to None."""\n' + " return None if v == [] else v" + ) + summary = docstring or class_name doc_block = _render_class_docstring(summary, doc_fields)