From 649c04807fc88fbb71735dd34ccf8c5df1e84e7e Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 27 Feb 2026 09:46:43 +0100 Subject: [PATCH 1/2] NGSTACK-1017 add new optional param for nullable required properties, update readme --- README.md | 2 ++ src/DependencyInjection/Configuration.php | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ae1412b..01faaa5 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ api_platform_extras: enabled: false #Mark schema properties as required by default when the type is not nullable. default_required_properties: false + #Additionally mark nullable types as required - safe to use if api_platform.defaults.normalization_context.skip_null_values set to false (default true). + nullable_required: false #Add @id as an optional property to all POST, PUT and PATCH schemas. jsonld_update_schema: false # NOT IMPLEMENTED YET diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 32ce8c8..2436b6f 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -29,7 +29,11 @@ public function getConfigTreeBuilder(): TreeBuilder ->children() ->booleanNode('default_required_properties') ->defaultFalse() - ->info('Mark schema properties as required by default when type is not nullable.') + ->info('Mark schema properties as required by default when type is not nullable - Only output schemas.') + ->end() + ->booleanNode('nullable_required') + ->defaultFalse() + ->info('Additionally mark nullable types as required - safe to use if api_platform.defaults.normalization_context.skip_null_values set to false (default true).') ->end() ->booleanNode('jsonld_update_schema') ->defaultFalse() From 93c72b73ab9a8ef0a1d0e49c1bd0f3df1d85c385 Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 27 Feb 2026 09:47:31 +0100 Subject: [PATCH 2/2] NGSTACK-1017 adjust property metadata decorator logic and update compiler pass --- .../Metadata/Property/PropertyMetadataFactoryDecorator.php | 7 +++++-- .../CompilerPass/SchemaDecorationCompilerPass.php | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ApiPlatform/JsonSchema/Metadata/Property/PropertyMetadataFactoryDecorator.php b/src/ApiPlatform/JsonSchema/Metadata/Property/PropertyMetadataFactoryDecorator.php index 6b0c64b..7b60503 100644 --- a/src/ApiPlatform/JsonSchema/Metadata/Property/PropertyMetadataFactoryDecorator.php +++ b/src/ApiPlatform/JsonSchema/Metadata/Property/PropertyMetadataFactoryDecorator.php @@ -13,6 +13,7 @@ final class PropertyMetadataFactoryDecorator implements PropertyMetadataFactoryI { public function __construct( private PropertyMetadataFactoryInterface $decorated, + private bool $nullableRequired, ) {} public function create(string $resourceClass, string $property, array $options = []): ApiProperty @@ -23,8 +24,10 @@ public function create(string $resourceClass, string $property, array $options = if ( ($options['schema_type'] ?? null) === Schema::TYPE_OUTPUT - - && $type !== null && $type::class !== NullableType::class + && ( + ($type !== null && $this->nullableRequired) + || ($type !== null && $type::class !== NullableType::class) + ) ) { return $propertyMetadata->withRequired(true); } diff --git a/src/DependencyInjection/CompilerPass/SchemaDecorationCompilerPass.php b/src/DependencyInjection/CompilerPass/SchemaDecorationCompilerPass.php index 38deb6a..9bb2b53 100644 --- a/src/DependencyInjection/CompilerPass/SchemaDecorationCompilerPass.php +++ b/src/DependencyInjection/CompilerPass/SchemaDecorationCompilerPass.php @@ -49,6 +49,7 @@ public function process(ContainerBuilder $container): void ->setDefinition('netgen.api_platform_extras.metadata.property.metadata_factory', new Definition(PropertyMetadataFactoryDecorator::class)) ->setArguments([ new Reference('netgen.api_platform_extras.metadata.property.metadata_factory.inner'), + $container->getParameter(sprintf('%s.nullable_required', self::BASE_FEATURE_PATH)), ]) ->setDecoratedService('api_platform.metadata.property.metadata_factory', null, 19); }