pydantic-enhanced-serializer


Namepydantic-enhanced-serializer JSON
Version 2.1.1 PyPI version JSON
download
home_pagehttps://github.com/adamsussman/pydantic-enhanced-serializer
SummaryPydantic extension that allows user selection of object fields or expansions inline when serializing models
upload_time2024-02-14 20:20:10
maintainer
docs_urlNone
authorAdam Sussman
requires_python
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# Better pydantic serialization for API use cases

Enhance pydantic's output serialization with features that can help make better APIs:

1) Output only fields and sets of fields requested by the caller, instead of all fields.

For example:

```
    api caller: Give me a User object with only the email and id fields.

    api response: Ok, instead of the usual 20 User fields, here is the object with only two.
```

2) Expand field values into more complex objects when requested

```
    api caller: Give me 10 Blog objects AND the User Objects that created them in ONE API response.

    api response: Ok, in addition to Blog.user_id, I will also give you Blog.User and its fields.
```


Both features are useful if you are using pydantic models to drive
REST APIs (ie: FastAPI) and you want to emulate the field/expansion
request model of GraphQL or other sophisticated APIs.

## Features

* Simply formatted "Fields" Request: When serializing a model, specify which fields you want and get ONLY those fields
* "Field Sets": Ask for specific fields or named groupings of fields
* "Expansions": Create new field names that "expand" into bigger objects via complex loading (for example,
  if you have a user id field, you can ask for the entire user object to be loaded and included
  in the serialization.
* Nested Model: Full support for nested models, lists of models, etc...
* Schema: Augment pydantic json schema generation with fieldset options
* Integration examples are given for:
    - Django Ninja
    - FastAPI
    - Flask

## Installation

```console
$ pip install pydantic-enhanced-serializer
```

## Help


See [documentation](https://github.com/adamsussman/pydantic-enhanced-serializer/tree/main/docs) for full details.

## Quickstart Example - Python

Basically: use `render_fieldset_model` instead of `model.model_dump()` or `model.model_dump_json()`.

Note that `render_fieldset_model` is an async function, so you may need
to await it, depending on your application.

```Python
    from typing import ClassVar

    from pydantic import BaseModel
    from pydantic_enhanced_serializer import render_fieldset_model, FieldsetConfig

    class MyModel(BaseModel):
        field_1: str
        field_2: str
        field_3: str
        field_4: str
        expensive_field_5: str
        expensive_field_6: str

        # This is the key config
        fieldset_config: ClassVar = FieldsetConfig(
            fieldsets = {
                "default": ["field_1", "field_2"],
                "extra": ["field_3", "field_4"],
            }
        )
```

Get only "default" fields:

```Python
    model = MyModel(
        field_1="field1 value",
        field_2="field2 value",
        field_3="field3 value",
        field_4="field4 value",
        expensive_field_5="field5 value",
        expensive_field_6="field6 value",
    )

    # instead of model.model_dump() do:
    result = await render_fieldset_model(
        model=model,
        fieldsets=[]
    )
```

Result:

```Python
    # Only "default" fieldset fields returned
    result == {
        "field_1": "field1 value",
        "field_2": "field2 value",
    }
```

Ask for specific fields:

```Python
    result = await render_fieldset_model(
        model=model,
        fieldsets=["extra", "expensive_field_5"],
    )
```

Result:

```Python
    # "default" fieldset fields, "extra" fieldset fields and
    # "expensive_field_5" returned, but NOT "expensive_field_6"
    result == {
        "field_1": "field1 value",
        "field_2": "field2 value",
        "field_3": "field3 value",
        "field_4": "field4 value",
        "expensive_field_5": field5 value",
    }
```

## Nested Fields example

```Python
    class SubModel(BaseModel):
        subfield1: str
        subfield2: str

        fieldset_config: ClassVar = FieldsetConfig(
            fieldsets = {
                "default": ["subfield1"],
            }
        )

    class MyModel(BaseModel):
        field1: str
        subfield: SubModel

        fieldset_config: ClassVar = FieldsetConfig(
            fieldsets = {
                "default": ["field1"],
            }
        )

    result = await render_fieldset_model(
        model=mymodel_instance,
        fields=["subfield.field2"]
    )
```

## License

This project is licensed under the terms of the MIT license.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/adamsussman/pydantic-enhanced-serializer",
    "name": "pydantic-enhanced-serializer",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Adam Sussman",
    "author_email": "adam.sussman@gmail.com",
    "download_url": "",
    "platform": null,
    "description": "\n# Better pydantic serialization for API use cases\n\nEnhance pydantic's output serialization with features that can help make better APIs:\n\n1) Output only fields and sets of fields requested by the caller, instead of all fields.\n\nFor example:\n\n```\n    api caller: Give me a User object with only the email and id fields.\n\n    api response: Ok, instead of the usual 20 User fields, here is the object with only two.\n```\n\n2) Expand field values into more complex objects when requested\n\n```\n    api caller: Give me 10 Blog objects AND the User Objects that created them in ONE API response.\n\n    api response: Ok, in addition to Blog.user_id, I will also give you Blog.User and its fields.\n```\n\n\nBoth features are useful if you are using pydantic models to drive\nREST APIs (ie: FastAPI) and you want to emulate the field/expansion\nrequest model of GraphQL or other sophisticated APIs.\n\n## Features\n\n* Simply formatted \"Fields\" Request: When serializing a model, specify which fields you want and get ONLY those fields\n* \"Field Sets\": Ask for specific fields or named groupings of fields\n* \"Expansions\": Create new field names that \"expand\" into bigger objects via complex loading (for example,\n  if you have a user id field, you can ask for the entire user object to be loaded and included\n  in the serialization.\n* Nested Model: Full support for nested models, lists of models, etc...\n* Schema: Augment pydantic json schema generation with fieldset options\n* Integration examples are given for:\n    - Django Ninja\n    - FastAPI\n    - Flask\n\n## Installation\n\n```console\n$ pip install pydantic-enhanced-serializer\n```\n\n## Help\n\n\nSee [documentation](https://github.com/adamsussman/pydantic-enhanced-serializer/tree/main/docs) for full details.\n\n## Quickstart Example - Python\n\nBasically: use `render_fieldset_model` instead of `model.model_dump()` or `model.model_dump_json()`.\n\nNote that `render_fieldset_model` is an async function, so you may need\nto await it, depending on your application.\n\n```Python\n    from typing import ClassVar\n\n    from pydantic import BaseModel\n    from pydantic_enhanced_serializer import render_fieldset_model, FieldsetConfig\n\n    class MyModel(BaseModel):\n        field_1: str\n        field_2: str\n        field_3: str\n        field_4: str\n        expensive_field_5: str\n        expensive_field_6: str\n\n        # This is the key config\n        fieldset_config: ClassVar = FieldsetConfig(\n            fieldsets = {\n                \"default\": [\"field_1\", \"field_2\"],\n                \"extra\": [\"field_3\", \"field_4\"],\n            }\n        )\n```\n\nGet only \"default\" fields:\n\n```Python\n    model = MyModel(\n        field_1=\"field1 value\",\n        field_2=\"field2 value\",\n        field_3=\"field3 value\",\n        field_4=\"field4 value\",\n        expensive_field_5=\"field5 value\",\n        expensive_field_6=\"field6 value\",\n    )\n\n    # instead of model.model_dump() do:\n    result = await render_fieldset_model(\n        model=model,\n        fieldsets=[]\n    )\n```\n\nResult:\n\n```Python\n    # Only \"default\" fieldset fields returned\n    result == {\n        \"field_1\": \"field1 value\",\n        \"field_2\": \"field2 value\",\n    }\n```\n\nAsk for specific fields:\n\n```Python\n    result = await render_fieldset_model(\n        model=model,\n        fieldsets=[\"extra\", \"expensive_field_5\"],\n    )\n```\n\nResult:\n\n```Python\n    # \"default\" fieldset fields, \"extra\" fieldset fields and\n    # \"expensive_field_5\" returned, but NOT \"expensive_field_6\"\n    result == {\n        \"field_1\": \"field1 value\",\n        \"field_2\": \"field2 value\",\n        \"field_3\": \"field3 value\",\n        \"field_4\": \"field4 value\",\n        \"expensive_field_5\": field5 value\",\n    }\n```\n\n## Nested Fields example\n\n```Python\n    class SubModel(BaseModel):\n        subfield1: str\n        subfield2: str\n\n        fieldset_config: ClassVar = FieldsetConfig(\n            fieldsets = {\n                \"default\": [\"subfield1\"],\n            }\n        )\n\n    class MyModel(BaseModel):\n        field1: str\n        subfield: SubModel\n\n        fieldset_config: ClassVar = FieldsetConfig(\n            fieldsets = {\n                \"default\": [\"field1\"],\n            }\n        )\n\n    result = await render_fieldset_model(\n        model=mymodel_instance,\n        fields=[\"subfield.field2\"]\n    )\n```\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Pydantic extension that allows user selection of object fields or expansions inline when serializing models",
    "version": "2.1.1",
    "project_urls": {
        "Homepage": "https://github.com/adamsussman/pydantic-enhanced-serializer"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b7e1153d9c8d0b764abb5fcd1c2d5ddc8c0c10fc6d21ff2ba3c35f5343fa48c0",
                "md5": "3508e1c10f9b0e998d9c379a40ac5335",
                "sha256": "71641483342d9ca38acd5398c1da32afa526d5517f0e153ed801f06d6365888d"
            },
            "downloads": -1,
            "filename": "pydantic_enhanced_serializer-2.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3508e1c10f9b0e998d9c379a40ac5335",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 16123,
            "upload_time": "2024-02-14T20:20:10",
            "upload_time_iso_8601": "2024-02-14T20:20:10.744849Z",
            "url": "https://files.pythonhosted.org/packages/b7/e1/153d9c8d0b764abb5fcd1c2d5ddc8c0c10fc6d21ff2ba3c35f5343fa48c0/pydantic_enhanced_serializer-2.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-14 20:20:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "adamsussman",
    "github_project": "pydantic-enhanced-serializer",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "pydantic-enhanced-serializer"
}
        
Elapsed time: 0.18283s