Description
Structured Output currently uses the PHP property name as the JSON Schema key, and the dedicated StructuredOutput\Serializer intentionally ignores Serializer naming metadata (#[SerializedName], name converters) so schema generation and hydration stay aligned (see #937 / #940).
That is a solid default, but there is no first-class way to expose a different JSON key to the model while keeping idiomatic PHP property names.
Example use case: PHP / domain code wants restBetweenRounds, but persisted JSON or an external contract already uses rest_between_rounds. Today the only options are:
- rename the PHP property to match the JSON key (awkward in PHP), or
- maintain custom mapping outside Symfony AI (easy to drift from the generated schema).
#[Schema] also has no name (or equivalent) argument today.
Proposed direction
One of (or a combination of):
#[Schema(name: 'rest_between_rounds')] — used by the JsonSchema Factory as the property key in properties / required, and respected by the Structured Output serializer when denormalizing.
- Honor
#[SerializedName] in both schema generation and the dedicated Structured Output serializer (same attribute as Symfony Serializer).
- Optional name converter / service injected into the JsonSchema Factory + Structured Output serializer (opt-in, default = current behavior: PHP property name).
Whatever the API, schema keys and hydration must stay in sync (the #937 lesson).
Benefits
- Idiomatic camelCase PHP DTOs
- Stable/snake_case (or legacy) JSON contracts for models / storage when needed
- No custom mapping layers that can diverge from the generated schema
Example (illustrative)
final readonly class CircuitMetadata
{
public function __construct(
#[Schema(
name: 'rest_between_rounds',
description: 'Rest between rounds in seconds',
minimum: 0,
)]
public int $restBetweenRounds,
) {}
}
Generated schema / model JSON would use rest_between_rounds; PHP keeps $restBetweenRounds.
Happy to discuss whether Schema(name: …), SerializedName, or an opt-in name converter is the preferred Symfony AI approach.
Description
Structured Output currently uses the PHP property name as the JSON Schema key, and the dedicated
StructuredOutput\Serializerintentionally ignores Serializer naming metadata (#[SerializedName], name converters) so schema generation and hydration stay aligned (see #937 / #940).That is a solid default, but there is no first-class way to expose a different JSON key to the model while keeping idiomatic PHP property names.
Example use case: PHP / domain code wants
restBetweenRounds, but persisted JSON or an external contract already usesrest_between_rounds. Today the only options are:#[Schema]also has noname(or equivalent) argument today.Proposed direction
One of (or a combination of):
#[Schema(name: 'rest_between_rounds')]— used by the JsonSchema Factory as the property key inproperties/required, and respected by the Structured Output serializer when denormalizing.#[SerializedName]in both schema generation and the dedicated Structured Output serializer (same attribute as Symfony Serializer).Whatever the API, schema keys and hydration must stay in sync (the #937 lesson).
Benefits
Example (illustrative)
Generated schema / model JSON would use
rest_between_rounds; PHP keeps$restBetweenRounds.Happy to discuss whether
Schema(name: …),SerializedName, or an opt-in name converter is the preferred Symfony AI approach.