Skip to content

Commit 82ff30e

Browse files
giulio-leoneCopilot
authored andcommitted
refactor: extract Pydantic serialization into shared utility
Extract the duplicated Pydantic BaseModel serialization logic from both lite_llm.py and tracing.py into a shared serialize_pydantic_model() helper in utils/serialization_utils.py. This ensures future changes to Pydantic serialization are made in a single place. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 32adb06 commit 82ff30e

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

src/google/adk/models/lite_llm.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
from pydantic import Field
5252
from typing_extensions import override
5353

54+
from ..utils.serialization_utils import serialize_pydantic_model
55+
5456
from ..utils._google_client_headers import merge_tracking_headers
5557
from .base_llm import BaseLlm
5658
from .llm_request import LlmRequest
@@ -493,8 +495,9 @@ def _safe_json_serialize(obj) -> str:
493495
"""
494496

495497
try:
496-
if isinstance(obj, BaseModel):
497-
return json.dumps(obj.model_dump(), default=str)
498+
serialized = serialize_pydantic_model(obj)
499+
if serialized is not None:
500+
return serialized
498501
# Try direct JSON serialization first
499502
return json.dumps(obj, ensure_ascii=False)
500503
except (TypeError, OverflowError):

src/google/adk/telemetry/tracing.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565

6666
from .. import version
6767
from ..utils.model_name_utils import is_gemini_model
68+
from ..utils.serialization_utils import serialize_pydantic_model
6869
from ._experimental_semconv import is_experimental_semconv
6970
from ._experimental_semconv import maybe_log_completion_details
7071
from ._experimental_semconv import set_operation_details_attributes_from_request
@@ -117,8 +118,9 @@ def _safe_json_serialize(obj) -> str:
117118
"""
118119

119120
try:
120-
if isinstance(obj, BaseModel):
121-
return json.dumps(obj.model_dump(), default=str)
121+
serialized = serialize_pydantic_model(obj)
122+
if serialized is not None:
123+
return serialized
122124
# Try direct JSON serialization first
123125
return json.dumps(
124126
obj, ensure_ascii=False, default=lambda o: '<not serializable>'
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Shared serialization utilities for Pydantic models."""
16+
17+
import json
18+
from typing import Any
19+
from typing import Optional
20+
21+
from pydantic import BaseModel
22+
23+
24+
def serialize_pydantic_model(obj: Any) -> Optional[str]:
25+
"""Serialize a Pydantic BaseModel to a JSON string.
26+
27+
Args:
28+
obj: The object to check and serialize.
29+
30+
Returns:
31+
A JSON string if the object is a Pydantic BaseModel, or None otherwise.
32+
"""
33+
if isinstance(obj, BaseModel):
34+
return json.dumps(obj.model_dump(), default=str)
35+
return None

0 commit comments

Comments
 (0)