DEV Community

whchi
whchi

Posted on

1

How to restrict json api response format with python

summary

Always use pydantic module

content

API design can be a challenging task, particularly when it comes to deciding on the appropriate output format. One common guide for designing JSON APIs is the simple specification provided by the following resource: https://github.com/omniti-labs/jsend.

However, it can be difficult to ensure that team members consistently adhere to these rules, which can require substantial time investment for reviewing pull requests.

To promote uniformity in API formatting, the most effective strategy may be to incorporate the formatting rules directly into your code. In the following example, I will illustrate how this can be accomplished using Python.

There's a static type checking module called pydantic which enforces type hints at runtime, and provides user friendly errors when data is invalid.

Below are examples of how this can be done using Python in jsend.

  • response example
from enum import Enum
from typing import Generic, List, TypeVar

from pydantic import BaseModel, Field, validator
from pydantic.generics import GenericModel

T = TypeVar('T')

class ResponseStatusEnum(str, Enum):
    SUCCESS = 'success'
    FAIL = 'fail'
    ERROR = 'error'

class ResponseBaseModel(GenericModel, Generic[T]):
    data: T | None = None
    message: str | None = ''
    status: str = ResponseStatusEnum.success

    class Config:
        use_enum_values = True
Enter fullscreen mode Exit fullscreen mode

sometimes you will need to return data with pagination, here's the example

  • paginate response example

class PageModel(GenericModel, Generic[T]):
    items: List[T] = []
    total: int
    current_page: int
    last_page: int | None
    prev_page: int | None
    next_page: int | None
    per_page: int

class PaginateResponseBaseModel(GenericModel, Generic[T]):
    data: PageModel[T]
    message: str | None = ''
    status: ResponseStatusEnum = ResponseStatusEnum.SUCCESS

    class Config:
        use_enum_values = True

Enter fullscreen mode Exit fullscreen mode
  • to use it(FastAPI)
from datetime import datetime

class ExampleEntity(BaseModel):
    id: int
    name: str
    age: int
    nick_name: str | None
    created_at: datetime | None = None
    updated_at: datetime | None = None

class GetExampleResponse(ResponseBaseModel[ExampleEntity]):
    data: ExampleEntity

class GetPaginateExamplesResponse(PaginateResponseBaseModel[ExampleEntity]):
    data: PageModel[ExampleEntity]

router = APIRouter()

# {data: {id, name, age, created_at, updated_at}, message, status}
@router.get('/examples/{id}')
def get_example(id) -> GetExampleResponse:
    """
    Returns:
        json: {
            data: { id, name, age, created_at, updated_at },
            message,
            status
        }
    """
    data = repo.get_examples(id)
    return GetExampleResponse(data=data)

@router.get('/paginate-examples/{id}')
def get_examples(id, page:int = 1, per_page: int = 1) -> GetPaginateExamplesResponse:
    """
    Returns:
        json: {
            data: {
                items: [{id, name, age, created_at, updated_at}],
                total,
                current_page,
                last_page,
                prev_page,
                next_page,
                per_page,
            },
            message,
            status
        }
    """
    data = repo.get_examples_with_paginate(id, page, per_page)
    return GetPaginateExamplesResponse(data=data)

Enter fullscreen mode Exit fullscreen mode

Then, all response will be restricted to the formats

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️