8

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.

saravana kumar
  • 255
  • 1
  • 3
  • 10

4 Answers4

13

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'}

YeJun
  • 309
  • 1
  • 6
6

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

from pydantic import BaseModel

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.

Note that in pydantic V2 this configuration changed to populate_by_name = True docs.

  • `allow_population_by_field_name=True` didn't work for me.. as per [the docs](https://docs.pydantic.dev/latest/usage/model_config/#populate-by-name) I used: `populate_by_name = True` – nihilok Aug 07 '23 at 11:26
  • It changed in V2, in 1.10 was allow_population_by_field_name [docs](https://docs.pydantic.dev/1.10/usage/model_config/]), I will update the answer – giuliano-oliveira Aug 07 '23 at 15:19
4

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)

Son Nguyen
  • 187
  • 1
  • 6
-4

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

pepper
  • 353
  • 1
  • 7