From 85e9f0391a9d9a5e616c5d4c4abfb25e6e61c781 Mon Sep 17 00:00:00 2001 From: mikemikimike <13286568797@163.com> Date: Fri, 28 Aug 2026 01:06:05 +0800 Subject: [PATCH] fix: preserve schema metadata for nullable anyOf --- .../types/test_schema_from_json_schema.py | 26 +++++++++++++++++++ google/genai/types.py | 6 +++++ 2 files changed, 32 insertions(+) diff --git a/google/genai/tests/types/test_schema_from_json_schema.py b/google/genai/tests/types/test_schema_from_json_schema.py index 04a72c45e..e08fe2f77 100644 --- a/google/genai/tests/types/test_schema_from_json_schema.py +++ b/google/genai/tests/types/test_schema_from_json_schema.py @@ -114,6 +114,32 @@ def test_nullable_conversion(): assert set(vertex_ai_not_none_field_names2) == set(['type', 'nullable']) +def test_nullable_any_of_preserves_schema_metadata(): + """Test that nullable any_of conversion preserves schema metadata.""" + json_schema = types.JSONSchema( + any_of=[ + types.JSONSchema(type='string'), + types.JSONSchema(type='null'), + ], + description='description', + title='title', + ) + + gemini_api_schema = types.Schema.from_json_schema(json_schema=json_schema) + vertex_ai_schema = types.Schema.from_json_schema( + json_schema=json_schema, api_option='VERTEX_AI' + ) + expected_schema = types.Schema( + type='STRING', + nullable=True, + description='description', + title='title', + ) + + assert gemini_api_schema == expected_schema + assert vertex_ai_schema == expected_schema + + def test_nullable_in_union_like_type_conversion(): """Test conversion of JSONSchema.nullable to Schema.nullable""" json_schema1 = types.JSONSchema( diff --git a/google/genai/types.py b/google/genai/types.py index 87aec0a50..3db9d83ef 100644 --- a/google/genai/types.py +++ b/google/genai/types.py @@ -3470,11 +3470,17 @@ def convert_json_schema( # If we found both parts, unwrap them into a single schema. if nullable_part and type_part: default_value = schema.default + description_value = schema.description + title_value = schema.title schema = type_part schema.nullable = True # Carry the default value over to the unwrapped schema if default_value is not None: schema.default = default_value + if description_value is not None: + schema.description = description_value + if title_value is not None: + schema.title = title_value if ref: visited_refs.remove(ref)