Skip to content

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

@vdusek

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.

Metadata

Metadata

Assignees

Labels

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

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions