diff --git a/modules/openapi-generator/src/main/resources/php-symfony/serialization/JmsSerializer.mustache b/modules/openapi-generator/src/main/resources/php-symfony/serialization/JmsSerializer.mustache
index 6c93e947f425..16a5504c886d 100644
--- a/modules/openapi-generator/src/main/resources/php-symfony/serialization/JmsSerializer.mustache
+++ b/modules/openapi-generator/src/main/resources/php-symfony/serialization/JmsSerializer.mustache
@@ -9,6 +9,7 @@ use JMS\Serializer\Serializer;
use JMS\Serializer\Visitor\Factory\XmlDeserializationVisitorFactory;
use DateTime;
use RuntimeException;
+use JMS\Serializer\Exception\RuntimeException as SerializerRuntimeException;
class JmsSerializer implements SerializerInterface
{
@@ -122,7 +123,7 @@ class JmsSerializer implements SerializerInterface
$enum = $type::tryFrom($data);
if (!$enum) {
- throw new RuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
+ throw new SerializerRuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
}
return $enum;
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java
index 291d25da5ca5..7875dabe9727 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/php/PhpSymfonyServerCodegenTest.java
@@ -242,6 +242,76 @@ public void testPetstoreDottedEnumRefQueryParameterUsesShortClassInApiInterface(
output.deleteOnExit();
}
+ /**
+ * Guards {@code php-symfony} {@code JmsSerializer.mustache}: invalid query values for a generated PHP
+ * {@code BackedEnum} are deserialized in {@code JmsSerializer::deserializeString()}. The generated
+ * {@code DefaultController} wraps {@code deserialize(...)} with {@code catch (SerializerRuntimeException)},
+ * an alias of {@code JMS\Serializer\Exception\RuntimeException}. Only the unknown-enum branch must throw that
+ * type; other string-deserialization errors may keep using PHP's global {@code RuntimeException}.
+ *
+ * This test asserts the generated {@code JmsSerializer.php} keeps {@code use RuntimeException;} and adds
+ * {@code use JMS\Serializer\Exception\RuntimeException as SerializerRuntimeException;}, throws
+ * {@code SerializerRuntimeException} for {@code tryFrom} failure, and that {@code DefaultController.php} still
+ * catches {@code SerializerRuntimeException}.
+ *
+ * Spec: {@code src/test/resources/3_1/php-symfony/jms-enum-query-invalid-deserialization.yaml}. Background:
+ * {@code fix_jms_enum_ex.md}.
+ */
+ @Test
+ public void testJmsSerializerUsesJmsRuntimeExceptionForBackedEnumStringDeserializationErrors() throws Exception {
+ Map properties = new HashMap<>();
+ properties.put("invokerPackage", "Org\\OpenAPITools\\PetstoreEnum");
+
+ File output = Files.createTempDirectory("test").toFile();
+
+ final CodegenConfigurator configurator = new CodegenConfigurator()
+ .setGeneratorName("php-symfony")
+ .setAdditionalProperties(properties)
+ .setInputSpec("src/test/resources/3_1/php-symfony/jms-enum-query-invalid-deserialization.yaml")
+ .setOutputDir(output.getAbsolutePath().replace("\\", "/"));
+
+ final ClientOptInput clientOptInput = configurator.toClientOptInput();
+ DefaultGenerator generator = new DefaultGenerator();
+ List files = generator.opts(clientOptInput).generate();
+
+ File jmsSerializer = files.stream()
+ .filter(f -> "JmsSerializer.php".equals(f.getName()) && f.getPath().contains("Service" + File.separator))
+ .findFirst()
+ .orElseThrow(() -> new AssertionError("JmsSerializer.php not generated"));
+
+ String jms = Files.readString(jmsSerializer.toPath(), StandardCharsets.UTF_8);
+
+ Assert.assertTrue(
+ jms.contains("Unknown %s value in %s enum"),
+ "Expected BackedEnum tryFrom failure message in generated JmsSerializer");
+ Assert.assertTrue(
+ Pattern.compile("^use RuntimeException;\\s*$", Pattern.MULTILINE).matcher(jms).find(),
+ "JmsSerializer should keep use RuntimeException for generic unsupported-type errors");
+ Assert.assertTrue(
+ jms.contains("use JMS\\Serializer\\Exception\\RuntimeException as SerializerRuntimeException;"),
+ "JmsSerializer must alias JMS RuntimeException as SerializerRuntimeException (same as DefaultController)");
+ Assert.assertTrue(
+ jms.contains("throw new SerializerRuntimeException(sprintf(\"Unknown %s value in %s enum\", $data, $type));"),
+ "Invalid BackedEnum tryFrom must throw SerializerRuntimeException so DefaultController catch applies");
+
+ File defaultController = files.stream()
+ .filter(f -> "DefaultController.php".equals(f.getName()) && f.getPath().contains("Controller" + File.separator))
+ .findFirst()
+ .orElseThrow(() -> new AssertionError("DefaultController.php not generated"));
+ String controller = Files.readString(defaultController.toPath(), StandardCharsets.UTF_8);
+ Assert.assertTrue(
+ controller.contains("use JMS\\Serializer\\Exception\\RuntimeException as SerializerRuntimeException;"),
+ "Expected DefaultController to catch SerializerRuntimeException alias");
+ Assert.assertTrue(
+ controller.contains("catch (SerializerRuntimeException $exception)"),
+ "Expected deserialize() to catch SerializerRuntimeException");
+
+ assertGeneratedPhpSyntaxValid(jmsSerializer);
+ assertGeneratedPhpSyntaxValid(defaultController);
+
+ output.deleteOnExit();
+ }
+
/**
* Optional {@code in: query} parameter: {@code required: false}, schema is an enum {@code $ref} with a valid
* {@code default} (see OpenAPI 3.x). Omitting the query key must be equivalent to sending that default; the
diff --git a/modules/openapi-generator/src/test/resources/3_1/php-symfony/jms-enum-query-invalid-deserialization.yaml b/modules/openapi-generator/src/test/resources/3_1/php-symfony/jms-enum-query-invalid-deserialization.yaml
new file mode 100644
index 000000000000..e3dbc168fb0c
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_1/php-symfony/jms-enum-query-invalid-deserialization.yaml
@@ -0,0 +1,25 @@
+openapi: 3.1.0
+info:
+ title: php-symfony JMS invalid query enum deserialization
+ version: '1.0'
+paths:
+ /pets:
+ get:
+ operationId: listPets
+ parameters:
+ - name: status
+ in: query
+ required: false
+ schema:
+ $ref: '#/components/schemas/Pet.Model.PetStatus'
+ responses:
+ '200':
+ description: OK
+components:
+ schemas:
+ Pet.Model.PetStatus:
+ type: string
+ enum:
+ - available
+ - pending
+ - sold
diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/Service/JmsSerializer.php b/samples/server/petstore/php-symfony/SymfonyBundle-php/Service/JmsSerializer.php
index 234056cf41d5..cccfc7d11300 100644
--- a/samples/server/petstore/php-symfony/SymfonyBundle-php/Service/JmsSerializer.php
+++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/Service/JmsSerializer.php
@@ -9,6 +9,7 @@
use JMS\Serializer\Visitor\Factory\XmlDeserializationVisitorFactory;
use DateTime;
use RuntimeException;
+use JMS\Serializer\Exception\RuntimeException as SerializerRuntimeException;
class JmsSerializer implements SerializerInterface
{
@@ -122,7 +123,7 @@ private function deserializeString($data, string $type)
$enum = $type::tryFrom($data);
if (!$enum) {
- throw new RuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
+ throw new SerializerRuntimeException(sprintf("Unknown %s value in %s enum", $data, $type));
}
return $enum;