This package extends sortedcontainers, a fast pure-Python library for sorted mutable collections, to work with Pydantic's models, validation, and serialization.
The easiest way to get started is to simply import SortedDict
, SortedList
, or SortedSet
from sortedcontainers_pydantic
instead of from sortedcontainers
.
from pydantic import BaseModel, TypeAdapter
from sortedcontainers_pydantic import SortedList
class MyModel(BaseModel):
sorted_list: SortedList[int]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedList([1, 2, 3]))
MyModel.model_validate_json('{"sorted_list": [3, 1, 2]}')
#> MyModel(sorted_list=SortedList([1, 2, 3]))
MyModel(sorted_list=[3, 1, 2]).model_dump_json()
#> '{"sorted_list":[1,2,3]}'
TypeAdapter(SortedList).validate_python([3, 1, 2])
#> SortedList([1, 2, 3])
TypeAdapter(SortedList).validate_json("[3, 1, 2]")
#> SortedList([1, 2, 3])
Reproducible example created by reprexlite v1.0.0
For additional alternative ways to declare types from this library, see the "Usage approaches" section below.
This library also supports key functions to customize sorting behavior. See the "Specifying a key function with Key
" section for further details.
sortedcontainers-pydantic is available on PyPI. You can install it with
pip install sortedcontainers-pydantic
It is also available on conda-forge. You can install it with
conda install sortedcontainers-pydantic --channel conda-forge
There are three different ways you can use sortedcontainers-pydantic
.
The library has subclasses of sortedcontainers's SortedDict
, SortedList
, and SortedSet
with Pydantic's special methods that enable validation and serialization. To use them, simply import classes of the same name from sortedcontainers_pydantic
.
from pydantic import BaseModel
from sortedcontainers_pydantic import SortedList
class MyModel(BaseModel):
sorted_list: SortedList[int]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedList([1, 2, 3]))
MyModel.model_validate_json('{"sorted_list": [3, 1, 2]}')
#> MyModel(sorted_list=SortedList([1, 2, 3]))
New in sortedcontainers-pydantic v2.0.0
The library has special annotation objects SortedDictPydanticAnnotation
, SortedListPydanticAnnotation
, and SortedSetPydanticAnnotation
that can be attached to sortedcontainers's SortedDict
, SortedList
, and SortedSet
, respectively, using typing.Annotated
. This implements the annotated pattern supported by Pydantic.
from typing import Annotated
from pydantic import BaseModel
from sortedcontainers import SortedList
from sortedcontainers_pydantic import SortedListPydanticAnnotation
class MyModel(BaseModel):
sorted_list: Annotated[SortedList[int], SortedListPydanticAnnotation]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedList([1, 2, 3]))
Unlike approach 1, the type being used is the original class from sortedcontainers and not a subclass.
New in sortedcontainers-pydantic v2.0.0
You can also use the wrapper types AnnotatedSortedDict
, AnnotatedSortedList
, or AnnotatedSortedSet
. These are simply type aliases implementing approach 2.
from pydantic import BaseModel
from sortedcontainers_pydantic import AnnotatedSortedList
AnnotatedSortedList
#> typing.Annotated[sortedcontainers.sortedlist.SortedList[~_T], <class 'sortedcontainers_pydantic.SortedListPydanticAnnotation'>]
class MyModel(BaseModel):
sorted_list: AnnotatedSortedList[int]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedList([1, 2, 3]))
New in sortedcontainers-pydantic v2.0.0
You can specify a key function to control sorting. The key should be a callable that takes a single argument. It will be run on every element to generate a key for making comparisons. To specify a key, instantiate the Key
special annotation object wrapping it, and attach it with typing.Annotated
. This works with any of the three approaches.
from typing import Annotated
from pydantic import BaseModel
from sortedcontainers_pydantic import Key, SortedList
class MyModel(BaseModel):
sorted_list: Annotated[SortedList[int], Key(lambda x: -x)]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedKeyList([3, 2, 1], key=<function MyModel.<lambda> at 0x10ae058a0>))
from typing import Annotated
from pydantic import BaseModel
from sortedcontainers import SortedList
from sortedcontainers_pydantic import Key, SortedListPydanticAnnotation
class MyModel(BaseModel):
sorted_list: Annotated[SortedList[int], SortedListPydanticAnnotation, Key(lambda x: -x)]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedKeyList([3, 2, 1], key=<function MyModel.<lambda> at 0x10aa4a520>))
from typing import Annotated
from pydantic import BaseModel
from sortedcontainers_pydantic import AnnotatedSortedList, Key
class MyModel(BaseModel):
sorted_list: Annotated[AnnotatedSortedList[int], Key(lambda x: -x)]
MyModel(sorted_list=[3.0, 1.0, 2.0])
#> MyModel(sorted_list=SortedKeyList([3, 2, 1], key=<function MyModel.<lambda> at 0x10ca65080>))
Reproducible examples created by reprexlite v1.0.0