Skip to content

Commit e31be05

Browse files
h3xxitclaude
andcommitted
feat(core): add explicit examples field to JsonSchema
JsonSchema previously accepted `examples` only via `extra="allow"`, leaving it untyped, undocumented, and invisible to type checkers. Declare it as Optional[List[JsonType]] so the JSON Schema `examples` keyword is a first-class, validated field. Supports PR universal-tool-calling-protocol#88 (OpenAPI converter examples parsing), which currently relies on the extra-field fallback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f6f51e9 commit e31be05

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

core/src/utcp/data/tool.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class JsonSchema(BaseModel):
3838
default: Optional schema default value.
3939
format: Optional schema format.
4040
additionalProperties: Optional schema additional properties.
41+
examples: Optional list of example values for the schema.
4142
"""
4243
schema_: Optional[str] = Field(None, alias="$schema")
4344
id_: Optional[str] = Field(None, alias="$id")
@@ -50,6 +51,7 @@ class JsonSchema(BaseModel):
5051
enum: Optional[List[JsonType]] = None
5152
const: Optional[JsonType] = None
5253
default: Optional[JsonType] = None
54+
examples: Optional[List[JsonType]] = None
5355
format: Optional[str] = None
5456
additionalProperties: Optional[Union[bool, "JsonSchema"]] = None
5557
pattern: Optional[str] = None

core/tests/data/__init__.py

Whitespace-only changes.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Tests for the JsonSchema model, including the `examples` field."""
2+
3+
from utcp.data.tool import JsonSchema, JsonSchemaSerializer
4+
5+
6+
def test_jsonschema_examples_field_is_typed():
7+
"""`examples` is a declared field, not just an extra attribute."""
8+
assert "examples" in JsonSchema.model_fields
9+
10+
schema = JsonSchema(type="string", examples=["user123", "user456"])
11+
assert schema.examples == ["user123", "user456"]
12+
13+
14+
def test_jsonschema_examples_default_none():
15+
"""`examples` defaults to None when absent."""
16+
schema = JsonSchema(type="string")
17+
assert schema.examples is None
18+
19+
20+
def test_jsonschema_examples_roundtrip():
21+
"""`examples` survives serialize -> validate roundtrip."""
22+
serializer = JsonSchemaSerializer()
23+
schema = JsonSchema(
24+
type="object",
25+
examples=[{"id": "user123", "name": "John Doe"}],
26+
)
27+
28+
as_dict = serializer.to_dict(schema)
29+
assert as_dict["examples"] == [{"id": "user123", "name": "John Doe"}]
30+
31+
restored = serializer.validate_dict(as_dict)
32+
assert restored.examples == schema.examples
33+
34+
35+
def test_jsonschema_examples_allows_mixed_json_types():
36+
"""`examples` accepts any JSON value (string, bool, number, object)."""
37+
schema = JsonSchema(examples=["a", True, 1, 1.5, None, {"k": "v"}, [1, 2]])
38+
assert schema.examples == ["a", True, 1, 1.5, None, {"k": "v"}, [1, 2]]

0 commit comments

Comments
 (0)