@@ -1202,6 +1202,115 @@ public function testDiscriminatorWithAllowExtraAttributesFalse()
12021202 $ this ->assertInstanceOf (DiscriminatorDummyTypeA::class, $ obj );
12031203 }
12041204
1205+ public function testNameConverterWithWrongCaseAndAllowExtraAttributesFalse ()
1206+ {
1207+ // When using a name converter with allow_extra_attributes=false,
1208+ // wrongly cased properties should trigger an exception
1209+ $ classMetadataFactory = new ClassMetadataFactory (new AttributeLoader ());
1210+ $ normalizer = new ObjectNormalizer (
1211+ $ classMetadataFactory ,
1212+ new CamelCaseToSnakeCaseNameConverter ()
1213+ );
1214+
1215+ // This should work - correct snake_case format
1216+ $ result = $ normalizer ->denormalize (
1217+ ['some_camel_case_property ' => 1 ],
1218+ NameConverterTestDummy::class,
1219+ null ,
1220+ [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false ]
1221+ );
1222+ $ this ->assertSame (1 , $ result ->someCamelCaseProperty );
1223+
1224+ // This should throw an exception - wrong camelCase format when snake_case is expected
1225+ $ this ->expectException (\Symfony \Component \Serializer \Exception \ExtraAttributesException:: class);
1226+ $ normalizer ->denormalize (
1227+ ['someCamelCaseProperty ' => 1 ],
1228+ NameConverterTestDummy::class,
1229+ null ,
1230+ [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => false ]
1231+ );
1232+ }
1233+
1234+ public function testNameConverterWithWrongCaseAndAllowExtraAttributesTrue ()
1235+ {
1236+ // When allow_extra_attributes=true (default), wrong format should be silently ignored
1237+ $ classMetadataFactory = new ClassMetadataFactory (new AttributeLoader ());
1238+ $ normalizer = new ObjectNormalizer (
1239+ $ classMetadataFactory ,
1240+ new CamelCaseToSnakeCaseNameConverter ()
1241+ );
1242+
1243+ // Wrong format should be ignored, property uses default value
1244+ $ result = $ normalizer ->denormalize (
1245+ ['someCamelCaseProperty ' => 999 ],
1246+ NameConverterTestDummy::class,
1247+ null ,
1248+ [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true ]
1249+ );
1250+ // Property should have default value since 'someCamelCaseProperty' was ignored
1251+ $ this ->assertSame (0 , $ result ->someCamelCaseProperty );
1252+
1253+ // Correct format should work normally
1254+ $ result = $ normalizer ->denormalize (
1255+ ['some_camel_case_property ' => 42 ],
1256+ NameConverterTestDummy::class,
1257+ null ,
1258+ [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true ]
1259+ );
1260+ $ this ->assertSame (42 , $ result ->someCamelCaseProperty );
1261+ }
1262+
1263+ public function testNameConverterWithMixedCorrectAndIncorrectFormat ()
1264+ {
1265+ // Test with multiple properties where some are correct, some are wrong
1266+ $ classMetadataFactory = new ClassMetadataFactory (new AttributeLoader ());
1267+ $ normalizer = new ObjectNormalizer (
1268+ $ classMetadataFactory ,
1269+ new CamelCaseToSnakeCaseNameConverter ()
1270+ );
1271+
1272+ // Mix of correct (snake_case) and incorrect (camelCase) should fail
1273+ $ this ->expectException (\Symfony \Component \Serializer \Exception \ExtraAttributesException::class);
1274+ $ this ->expectExceptionMessage ('someCamelCaseProperty ' );
1275+
1276+ $ normalizer ->denormalize (
1277+ [
1278+ 'some_camel_case_property ' => 1 , // Correct format
1279+ 'someCamelCaseProperty ' => 2 , // Wrong format - should trigger exception
1280+ 'another_property ' => 3 , // Correct format
1281+ ],
1282+ NameConverterTestDummyMultiple::class,
1283+ null ,
1284+ [AbstractNormalizer:: ALLOW_EXTRA_ATTRIBUTES => false ]
1285+ );
1286+ }
1287+
1288+ public function testNameConverterWithoutStrictModeStillWorks ()
1289+ {
1290+ // Ensure the default behavior (without allow_extra_attributes context) still works
1291+ $ classMetadataFactory = new ClassMetadataFactory (new AttributeLoader ());
1292+ $ normalizer = new ObjectNormalizer (
1293+ $ classMetadataFactory ,
1294+ new CamelCaseToSnakeCaseNameConverter ()
1295+ );
1296+
1297+ // Correct snake_case format should work
1298+ $ result1 = $ normalizer ->denormalize (
1299+ ['some_camel_case_property ' => 1 ],
1300+ NameConverterTestDummy::class
1301+ );
1302+ $ this ->assertSame (1 , $ result1 ->someCamelCaseProperty );
1303+
1304+ // Wrong format (camelCase instead of snake_case) is silently ignored
1305+ // when allow_extra_attributes is not set (defaults to true)
1306+ $ result2 = $ normalizer ->denormalize (
1307+ ['someCamelCaseProperty ' => 2 ],
1308+ NameConverterTestDummy::class
1309+ );
1310+ // Property keeps default value since wrong format was ignored
1311+ $ this ->assertSame (0 , $ result2 ->someCamelCaseProperty );
1312+ }
1313+
12051314 public function testNormalizeObjectWithGroupsAndIsPrefixedProperty ()
12061315 {
12071316 $ classMetadataFactory = new ClassMetadataFactory (new AttributeLoader ());
@@ -1756,3 +1865,20 @@ public function visibleGroup()
17561865 return $ this ->visibleGroup ;
17571866 }
17581867}
1868+
1869+ class NameConverterTestDummy
1870+ {
1871+ public function __construct (
1872+ public readonly int $ someCamelCaseProperty = 0 ,
1873+ ) {
1874+ }
1875+ }
1876+
1877+ class NameConverterTestDummyMultiple
1878+ {
1879+ public function __construct (
1880+ public readonly int $ someCamelCaseProperty = 0 ,
1881+ public readonly int $ anotherProperty = 0 ,
1882+ ) {
1883+ }
1884+ }
0 commit comments