⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@Maxcastel
Copy link
Contributor

@Maxcastel Maxcastel commented Dec 23, 2025

Q A
Branch? 4.2
Tickets Closes #7536
License MIT

ApiResource examples:

#[ApiResource(
    operations: [
        new Get(
            normalizationContext: [
                'attributes' => ['title', 'name', 'author' => ['name']],
            ],
        ),
        new Post(
            denormalizationContext: [
                'attributes' => ['title', 'name', 'author' => ['name']], 
            ],
            normalizationContext: [
                'attributes' => ['id', 'title', 'author' => ['id', 'name']],
            ],
        )
    ]
)]
class Book
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[Groups(['book:read'])]
    #[ORM\Column(type: 'string', length: 255)]
    public string $title = 'The book title';

    #[ORM\Column(type: 'string', length: 255)]
    private ?string $name = null;

    #[ORM\ManyToOne(targetEntity: Author::class)]
    #[ORM\JoinColumn(nullable: false)]
    private Author $author;
    
    #[ORM\Column(type: 'string', length: 20)]
    public string $isbn = '978-3-16-148410-0';

    // getters and setters
}
#[ApiResource]
class Author
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[Groups(['user:read', 'user:write'])]
    #[ORM\Column(type: 'string', length: 255)]
    private string $name;

    // getters and setters
}

Before

API response

/api/books/id GET:
api-books-id

API Docs

api-docs-Book-api_books_id_get

api-docs-Book-api_books_post

JSON Schema

bin/console api:openapi:export --output=swagger_docs.json

"application/json": {
    "schema": {
        "$ref": "#/components/schemas/Book"
    }
}
"Book": {
    "type": "object",
    "properties": {
        "id": {
            "readOnly": true,
            "type": "integer"
        },
        "title": {
            "default": "The book title",
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "author": {
            "type": "string",
            "format": "iri-reference",
            "example": "https://example.com/"
        },
        "isbn": {
            "default": "978-3-16-148410-0",
            "type": "string"
        }
    }
}

Now

API response

/api/books/id GET:
api-books-id

API Docs

api-docs-Book-api_books_id_get2

api-docs-Book-api_books_post2

JSON Schema

"application/json": {
    "schema": {
        "$ref": "#/components/schemas/Book-title_name_author.name"
    }
}
"Book-title_name_author.name": {
    "type": "object",
    "properties": {
        "title": {
            "default": "The book title",
            "type": "string"
        },
        "name": {
            "type": "string"
        },
        "author": {
            "$ref": "#/components/schemas/Author-name"
        }
    }
}
"Author-name": {
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        }
    }
}

@Maxcastel Maxcastel changed the title fix(JsonSchema): add support for attributes fix: add support for normalization/denormalization with attributes Dec 23, 2025
@soyuka
Copy link
Member

soyuka commented Dec 26, 2025

This looks nice, can you add a test on the JsonSchema generation (tests/Functional/JsonSchema/JsonSchemaTest.php) as I'm not sure that we'd gather the correct properties.

@Maxcastel Maxcastel force-pushed the fix/json-schema-api-docs-serialization-attributes branch from cda5443 to 36c1db8 Compare December 26, 2025 09:03
@Maxcastel
Copy link
Contributor Author

I rebased onto 4.2 to retrieve the code that fixes the 8 failing tests.

@Maxcastel Maxcastel force-pushed the fix/json-schema-api-docs-serialization-attributes branch from d3a767a to 4691c25 Compare December 26, 2025 20:17
@Maxcastel
Copy link
Contributor Author

This looks nice, can you add a test on the JsonSchema generation (tests/Functional/JsonSchema/JsonSchemaTest.php) as I'm not sure that we'd gather the correct properties.

Done in c2b0997 @soyuka

@Maxcastel Maxcastel marked this pull request as ready for review December 26, 2025 22:39
@soyuka soyuka requested a review from Copilot January 16, 2026 15:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for using the attributes context option in normalization and denormalization, similar to how serialization groups currently work. This allows developers to control which properties are exposed in API responses and accepted in requests through the attributes context, providing an alternative to serialization groups for controlling API visibility.

Changes:

  • Added support for attribute-based property filtering in normalization/denormalization contexts
  • Updated schema generation to reflect attribute-based filtering in OpenAPI documentation
  • Added comprehensive test coverage for the new attribute filtering functionality

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Metadata/Property/Factory/SerializerPropertyMetadataFactory.php Added logic to extract and apply normalization/denormalization attributes when determining property read/write/link permissions
src/JsonSchema/SchemaFactory.php Updated schema building to propagate attribute context to child properties and extract attributes from operation contexts
src/JsonSchema/DefinitionNameFactory.php Extended definition name generation to include attributes in the naming scheme alongside groups
tests/Functional/JsonSchema/JsonSchemaTest.php Added functional test verifying schema generation with attribute-based filtering
tests/Fixtures/TestBundle/ApiResource/ParentAttribute.php New fixture class demonstrating parent resource with attribute-based filtering
tests/Fixtures/TestBundle/ApiResource/ChildAttribute.php New fixture class demonstrating child resource in attribute filtering scenarios
src/Metadata/Tests/Property/Factory/SerializerPropertyMetadataFactoryTest.php Added unit tests for attribute-based property filtering logic
src/JsonSchema/Tests/SchemaFactoryTest.php Added unit tests for schema generation with serializer attributes
src/JsonSchema/Tests/Fixtures/ApiResource/ParentAttributeDummy.php New test fixture for schema factory attribute testing
src/JsonSchema/Tests/Fixtures/ApiResource/ChildAttributeDummy.php New test fixture for child resource in schema factory tests
src/JsonSchema/Tests/DefinitionNameFactoryTest.php Added test cases for definition name generation with attributes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

$parts[] = $key.'.'.$child;
}
} elseif (\is_string($key)) {
$parts[] = $key.'_'.$value;
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a string key exists with a string value (non-array), the logic concatenates key and value with an underscore. However, this appears to be treating the value as a property name, but it should likely just use the key. For example, if the input is ['author' => 'someValue'], this produces 'author_someValue' instead of just 'author'. This doesn't match the pattern used for array values (line 125) where only the key is used as a prefix.

Suggested change
$parts[] = $key.'_'.$value;
$parts[] = $key;

Copilot uses AI. Check for mistakes.
private ?int $id = null;

#[ORM\Column(length: 255)]
private ?string $name = null;
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name is ambiguous in the context of a ParentAttribute class. Consider renaming to something more descriptive like parentName or entityName to clarify its purpose and distinguish it from potential child names.

Copilot uses AI. Check for mistakes.
private ?int $id = null;

#[ORM\Column(length: 255)]
private ?string $title = null;
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property title in ParentAttributeDummy is ambiguous. Consider a more descriptive name like dummyTitle or resourceTitle to better convey its purpose in test scenarios.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants