How to inflect from snake case to camel case post the pydantic schema validations

Viewed 5164

I can able to find a way to convert camelcase type based request body to snake case one by using Alias Generator, But for my response, I again want to inflect snake case type to camel case type post to the schema validation. Is there any way I can achieve this?

Example: I do have a python dict as below,

{
 "title_name": "search001",
 "status_type": "New" 
}

And post to the pydantic schema validation my dict should convert snake case type to camel case as below,

{
 "titleName": "search001",
 "statusType": "New" 
}

How can I define a pydantic schema to achieve the above problem?

Thanks in advance.

4 Answers

You can use Alias Generator

from pydantic import BaseModel


def to_snake_case(string: str) -> str:
    return ''.join(['_' + i.lower() if i.isupper() else i for i in string]).lstrip('_')


class MyModel(BaseModel):
    titleName: str
    statusType: str

    class Config:
        alias_generator = to_snake_case


data = {
    "title_name": "search001",
    "status_type": "New"
}
print(MyModel(**data).dict()) # {'titleName': 'search001', 'statusType': 'New'}

You can use a combination of alias generator and the kwarg by_alias in .json or .dict:

from pydantic import BaseModel,Field

def to_camel(string: str) -> str:
    string_split = string.split('_')
    return string_split[0]+''.join(word.capitalize() for word in string_split[1:])


class Foo(BaseModel):
    title_name:str
    status_type:str
    class Config:
        alias_generator = to_camel

f = Foo.parse_raw("""
{
 "titleName": "search001",
 "statusType": "New" 
}
""")
print(f) # title_name='search001' status_type='New'
print(f.json(by_alias=True)) # {"titleName": "search001", "statusType": "New"}
print(f.json()) # {"title_name": "search001", "status_type": "New"}

Also, you can add allow_population_by_field_name=True in the Config class so that you can parse/initialize the model with the original field name or the alias name.

If you're using fastapi, you can leverage the fastapi_camelcase package as follow:

import uvicorn
from fastapi import FastAPI
from fastapi_camelcase import CamelModel


class User(CamelModel):
    first_name: str
    last_name: str
    age: int


app = FastAPI()


@app.get("/user/get", response_model=User)
async def get_user():
    return User(first_name="John", last_name="Doe", age=30)


@app.post("/user/create", response_model=User)
async def create_user(user: User):
    return user


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

I highly recommend u could try this.Using marshmallow.

from marshmallow import Schema, fields


def camelcase(s):
    parts = iter(s.split("_"))
    return next(parts) + "".join(i.title() for i in parts)


class CamelCaseSchema(Schema):
    """Schema that uses camel-case for its external representation
    and snake-case for its internal representation.
    """

    def on_bind_field(self, field_name, field_obj):
        field_obj.data_key = camelcase(field_obj.data_key or field_name)


# -----------------------------------------------------------------------------


class UserSchema(CamelCaseSchema):
    first_name = fields.Str(required=True)
    last_name = fields.Str(required=True)


schema = UserSchema()
loaded = schema.load({"firstName": "David", "lastName": "Bowie"})
print(loaded)  # => {'last_name': 'Bowie', 'first_name': 'David'}
dumped = schema.dump(loaded)
print(dumped)  # => {'lastName': 'Bowie', 'firstName': 'David'}

u could learn more in there docoument https://marshmallow.readthedocs.io/en/stable/examples.html

Related