Skip to content

Commit 3c18038

Browse files
🐛 Fix path encoding (fastapi#978)
1 parent 1c3289f commit 3c18038

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

fastapi/encoders.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from enum import Enum
2+
from pathlib import PurePath
23
from types import GeneratorType
34
from typing import Any, Callable, Dict, List, Set, Tuple, Union
45

@@ -73,6 +74,8 @@ def jsonable_encoder(
7374
)
7475
if isinstance(obj, Enum):
7576
return obj.value
77+
if isinstance(obj, PurePath):
78+
return str(obj)
7679
if isinstance(obj, (str, int, float, type(None))):
7780
return obj
7881
if isinstance(obj, dict):

tests/test_jsonable_encoder.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from datetime import datetime, timezone
22
from enum import Enum
3+
from pathlib import PurePath, PurePosixPath, PureWindowsPath
34

45
import pytest
56
from fastapi.encoders import jsonable_encoder
6-
from pydantic import BaseModel, ValidationError
7+
from pydantic import BaseModel, ValidationError, create_model
78

89
try:
910
from pydantic import Field
@@ -69,6 +70,19 @@ class ModelWithAlias(BaseModel):
6970
foo: str = Field(..., alias="Foo")
7071

7172

73+
@pytest.fixture(
74+
name="model_with_path", params=[PurePath, PurePosixPath, PureWindowsPath]
75+
)
76+
def fixture_model_with_path(request):
77+
class Config:
78+
arbitrary_types_allowed = True
79+
80+
ModelWithPath = create_model(
81+
"ModelWithPath", path=(request.param, ...), __config__=Config
82+
)
83+
return ModelWithPath(path=request.param("/foo", "bar"))
84+
85+
7286
def test_encode_class():
7387
person = Person(name="Foo")
7488
pet = Pet(owner=person, name="Firulais")
@@ -120,3 +134,11 @@ class MyModel(BaseModel):
120134
instance, custom_encoder={safe_datetime: lambda o: o.isoformat()}
121135
)
122136
assert encoded_instance["dt_field"] == instance.dt_field.isoformat()
137+
138+
139+
def test_encode_model_with_path(model_with_path):
140+
if isinstance(model_with_path.path, PureWindowsPath):
141+
expected = "\\foo\\bar"
142+
else:
143+
expected = "/foo/bar"
144+
assert jsonable_encoder(model_with_path) == {"path": expected}

0 commit comments

Comments
 (0)