Skip to content

Use alias_generator=to_camel on Pydantic models instead of manual per-field aliases #949

Description

@vdusek

Background

We're on Pydantic ≥2.11. Models in src/apify/_models.py and src/apify/storage_clients/_apify/_models.py map snake_case fields to the Apify API's camelCase, declaring each alias by hand:

actor_id: Annotated[str | None, Field(alias='actorId')] = None
actor_task_id: Annotated[str | None, Field(alias='actorTaskId')] = None

Proposal

Add alias_generator=to_camel to the shared config so aliases are derived:

from pydantic.alias_generators import to_camel

model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)

Fields then become actor_id: str | None = None and still bind to actorId. Currently 19 models repeat ConfigDict(populate_by_name=True, ...) while 11 (events in events/_types.py, the request-loader input models) have no config at all. A single base model carrying the config (including the generator) would cover both gaps.

Where it makes sense

  • Apply to the API-response models that already use camelCase aliases.
  • Keep explicit Field(alias=...) where the generated key would differ.
  • Subclasses of Crawlee storage models (ApifyKeyValueStoreMetadata, ApifyRequestQueueMetadata) should follow whatever Crawlee adopts.
  • Event models carry protocol-defined names, so check each before switching.

Scope

Refactor only. Generated aliases must match the current ones, guarded by tests.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

t-toolingIssues with this label are in the ownership of the tooling team.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions