Skip to content

Commit 14222be

Browse files
authored
Add more accurate JSON schema for Pydantic (#25)
* Add more accurate JSON schema for Pydantic * chore: Python 3.9 doesn't allow union types with |
1 parent f6a761b commit 14222be

3 files changed

Lines changed: 32 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ Changelog
55

66
Versions follow `Semantic Versioning <http://www.semver.org>`_
77

8-
`2.4.0`_ - 2024-04-02
8+
`2.5.0`_ - tbd
99
---------------------
10+
Changed
11+
~~~~~~~
12+
* Generate a more accurate JSON schema with Pydantic's ``BaseModel.model_json_schema()``. This
13+
includes a specification for string and byte representations.
1014

15+
`2.4.0`_ - 2024-04-02
16+
---------------------
1117
Added
1218
~~~~~
1319
* :class:`.ULID` objects are now properly serialized when used as Pydantic types `@Avihais12344 <https://github.com/Avihais12344>`_.
@@ -151,6 +157,7 @@ Changed
151157
* The package now has no external dependencies.
152158
* The test-coverage has been raised to 100%.
153159

160+
.. _2.5.0: https://github.com/mdomke/python-ulid/compare/2.4.0...2.5.0
154161
.. _2.4.0: https://github.com/mdomke/python-ulid/compare/2.3.0...2.4.0
155162
.. _2.3.0: https://github.com/mdomke/python-ulid/compare/2.2.0...2.3.0
156163
.. _2.2.0: https://github.com/mdomke/python-ulid/compare/2.1.0...2.2.0

tests/test_ulid.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from datetime import datetime
66
from datetime import timedelta
77
from datetime import timezone
8+
from typing import Optional
89
from typing import Union
910

1011
import pytest
@@ -168,7 +169,7 @@ def test_pydantic_protocol() -> None:
168169
ulid = ULID()
169170

170171
class Model(BaseModel):
171-
ulid: ULID
172+
ulid: Optional[ULID] = None
172173

173174
for value in [ulid, str(ulid), int(ulid), bytes(ulid)]:
174175
model = Model(ulid=value)
@@ -188,3 +189,23 @@ class Model(BaseModel):
188189
model_json = model.model_dump_json()
189190
assert isinstance(json.loads(model_json)["ulid"], str)
190191
assert Model.model_validate_json(model_json) == model
192+
193+
model_json_schema = model.model_json_schema()
194+
assert "properties" in model_json_schema
195+
assert "ulid" in model_json_schema["properties"]
196+
assert "anyOf" in model_json_schema["properties"]["ulid"]
197+
assert {
198+
"maxLength": 26,
199+
"minLength": 26,
200+
"pattern": "[A-Z0-9]{26}",
201+
"type": "string",
202+
} in model_json_schema["properties"]["ulid"]["anyOf"]
203+
assert {
204+
"maxLength": 16,
205+
"minLength": 16,
206+
"type": "string",
207+
"format": "binary",
208+
} in model_json_schema["properties"]["ulid"]["anyOf"]
209+
assert {
210+
"type": "null",
211+
} in model_json_schema["properties"]["ulid"]["anyOf"]

ulid/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler
259259
[
260260
core_schema.is_instance_schema(ULID),
261261
core_schema.no_info_plain_validator_function(ULID),
262+
core_schema.str_schema(pattern=r"[A-Z0-9]{26}", min_length=26, max_length=26),
263+
core_schema.bytes_schema(min_length=16, max_length=16),
262264
]
263265
),
264266
serialization=core_schema.to_string_ser_schema(

0 commit comments

Comments
 (0)