Improve json handling

This commit is contained in:
Jeremiah Lowin 2024-11-30 16:01:19 -05:00
commit 26ba6a226f
3 changed files with 21 additions and 5 deletions

View file

@ -1,5 +1,6 @@
"""Concrete resource implementations."""
import pydantic_core
import asyncio
import json
from pathlib import Path
@ -58,8 +59,8 @@ class FunctionResource(Resource):
if isinstance(result, str):
return result
try:
return json.dumps(result, default=pydantic.json.pydantic_encoder)
except TypeError:
return json.dumps(pydantic_core.to_jsonable_python(result))
except (TypeError, pydantic_core.PydanticSerializationError):
# If JSON serialization fails, try str()
return str(result)
except Exception as e:

View file

@ -1,5 +1,6 @@
"""FastMCP - A more ergonomic interface for MCP servers."""
import pydantic_core
from typing import Any, Literal, Optional, Union
from mcp.server import RequestContext
@ -14,7 +15,6 @@ from typing import Callable, Sequence
import inspect
import re
import pydantic.json
from mcp.server import Server as MCPServer
from mcp.server.stdio import stdio_server
from mcp.server.sse import SseServerTransport
@ -397,7 +397,7 @@ def _convert_to_content(value: Any) -> Sequence[Union[TextContent, ImageContent]
result.append(
TextContent(
type="text",
text=json.dumps(item, default=pydantic.json.pydantic_encoder),
text=json.dumps(pydantic_core.to_jsonable_python(item)),
)
)
return result
@ -414,7 +414,7 @@ def _convert_to_content(value: Any) -> Sequence[Union[TextContent, ImageContent]
return [
TextContent(
type="text",
text=json.dumps(value, indent=2, default=pydantic.json.pydantic_encoder),
text=json.dumps(pydantic_core.to_jsonable_python(value)),
)
]

View file

@ -1,3 +1,4 @@
from pydantic import BaseModel
import pytest
from fastmcp.resources import FunctionResource
@ -80,6 +81,20 @@ class TestFunctionResource:
with pytest.raises(ValueError, match="Error reading resource function://test"):
await resource.read()
async def test_basemodel_conversion(self):
"""Test handling of BaseModel types."""
class MyModel(BaseModel):
name: str
resource = FunctionResource(
uri="function://test",
name="test",
func=lambda: MyModel(name="test"),
)
content = await resource.read()
assert content == '{"name": "test"}'
async def test_custom_type_conversion(self):
"""Test handling of custom types."""