From 97c05c2015f0abf512a1538342d698a7403c5689 Mon Sep 17 00:00:00 2001 From: willwang Date: Thu, 13 Aug 2026 00:44:39 +0800 Subject: [PATCH] fix(pydantic): decode JSON pointer references --- src/openai/lib/_pydantic.py | 3 ++- tests/lib/test_pydantic.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/openai/lib/_pydantic.py b/src/openai/lib/_pydantic.py index 3cfe224cb1..df9bb3e4cd 100644 --- a/src/openai/lib/_pydantic.py +++ b/src/openai/lib/_pydantic.py @@ -2,6 +2,7 @@ import inspect from typing import Any, TypeVar +from urllib.parse import unquote from typing_extensions import TypeGuard import pydantic @@ -119,7 +120,7 @@ def resolve_ref(*, root: dict[str, object], ref: str) -> object: if not ref.startswith("#/"): raise ValueError(f"Unexpected $ref format {ref!r}; Does not start with #/") - path = ref[2:].split("/") + path = [unquote(key).replace("~1", "/").replace("~0", "~") for key in ref[2:].split("/")] resolved = root for key in path: value = resolved[key] diff --git a/tests/lib/test_pydantic.py b/tests/lib/test_pydantic.py index 754a15151c..9f486e05c5 100644 --- a/tests/lib/test_pydantic.py +++ b/tests/lib/test_pydantic.py @@ -7,11 +7,44 @@ import openai from openai._compat import PYDANTIC_V1 -from openai.lib._pydantic import to_strict_json_schema +from openai.lib._pydantic import resolve_ref, to_strict_json_schema, _ensure_strict_json_schema from .schema_types.query import Query +def test_resolve_ref_decodes_json_pointer_tokens() -> None: + schema: dict[str, object] = { + "$defs": { + "path/to model~v1": {"type": "string"}, + } + } + + assert resolve_ref(root=schema, ref="#/$defs/path~1to%20model~0v1") == {"type": "string"} + + +def test_strict_schema_inlines_escaped_ref() -> None: + schema: dict[str, object] = { + "$defs": {"path/to model~v1": {"type": "object", "properties": {"value": {"type": "string"}}}}, + "type": "object", + "properties": { + "result": { + "$ref": "#/$defs/path~1to%20model~0v1", + "description": "A custom result", + } + }, + } + + strict_schema = _ensure_strict_json_schema(schema, path=(), root=schema) + + assert strict_schema["properties"]["result"] == { + "type": "object", + "properties": {"value": {"type": "string"}}, + "required": ["value"], + "description": "A custom result", + "additionalProperties": False, + } + + def test_most_types() -> None: if not PYDANTIC_V1: assert openai.pydantic_function_tool(Query)["function"] == snapshot(