Skip to content

Commit 7d94b0e

Browse files
committed
[Core] Support map/object format for x-enum-varnames and x-enum-descriptions
The generator crashes with a ClassCastException when these vendor extensions are provided as a JSON object (map) instead of an array. Both formats are valid conventions used in the ecosystem (Redocly, Speakeasy, etc.). For map format, keys are matched to enum values via toEnumValue(key, dataType) to ensure correct matching regardless of language-specific value transformations.
1 parent c07f3a0 commit 7d94b0e

3 files changed

Lines changed: 98 additions & 16 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7028,17 +7028,31 @@ private String getUniqueEnumName(String name, List<Map<String, Object>> enumVars
70287028

70297029
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
70307030
if (vendorExtensions != null) {
7031-
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-varnames", "name");
7032-
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-descriptions", "enumDescription");
7031+
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-varnames", "name", dataType);
7032+
updateEnumVarsWithExtensions(enumVars, vendorExtensions, "x-enum-descriptions", "enumDescription", dataType);
70337033
}
70347034
}
70357035

7036-
private void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String extensionKey, String key) {
7036+
private void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String extensionKey, String key, String dataType) {
70377037
if (vendorExtensions.containsKey(extensionKey)) {
7038-
List<String> values = (List<String>) vendorExtensions.get(extensionKey);
7039-
int size = Math.min(enumVars.size(), values.size());
7040-
for (int i = 0; i < size; i++) {
7041-
enumVars.get(i).put(key, values.get(i));
7038+
Object extensionValue = vendorExtensions.get(extensionKey);
7039+
if (extensionValue instanceof List) {
7040+
List<String> values = (List<String>) extensionValue;
7041+
int size = Math.min(enumVars.size(), values.size());
7042+
for (int i = 0; i < size; i++) {
7043+
enumVars.get(i).put(key, values.get(i));
7044+
}
7045+
} else if (extensionValue instanceof Map) {
7046+
Map<String, String> valueMap = (Map<String, String>) extensionValue;
7047+
for (Map<String, Object> enumVar : enumVars) {
7048+
String enumValue = (String) enumVar.get("value");
7049+
for (Map.Entry<String, String> entry : valueMap.entrySet()) {
7050+
if (toEnumValue(entry.getKey(), dataType).equals(enumValue)) {
7051+
enumVar.put(key, entry.getValue());
7052+
break;
7053+
}
7054+
}
7055+
}
70427056
}
70437057
}
70447058
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -711,19 +711,46 @@ public void setParameterExampleValue(CodegenParameter p) {
711711
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
712712
if (vendorExtensions != null) {
713713
if (vendorExtensions.containsKey("x-enum-varnames")) {
714-
List<String> values = (List<String>) vendorExtensions.get("x-enum-varnames");
715-
int size = Math.min(enumVars.size(), values.size());
716-
717-
for (int i = 0; i < size; i++) {
718-
enumVars.get(i).put("name", toEnumVarName(values.get(i), dataType));
714+
Object extensionValue = vendorExtensions.get("x-enum-varnames");
715+
if (extensionValue instanceof List) {
716+
List<String> values = (List<String>) extensionValue;
717+
int size = Math.min(enumVars.size(), values.size());
718+
for (int i = 0; i < size; i++) {
719+
enumVars.get(i).put("name", toEnumVarName(values.get(i), dataType));
720+
}
721+
} else if (extensionValue instanceof Map) {
722+
Map<String, String> valueMap = (Map<String, String>) extensionValue;
723+
for (Map<String, Object> enumVar : enumVars) {
724+
String enumValue = (String) enumVar.get("value");
725+
for (Map.Entry<String, String> entry : valueMap.entrySet()) {
726+
if (toEnumValue(entry.getKey(), dataType).equals(enumValue)) {
727+
enumVar.put("name", toEnumVarName(entry.getValue(), dataType));
728+
break;
729+
}
730+
}
731+
}
719732
}
720733
}
721734

722735
if (vendorExtensions.containsKey("x-enum-descriptions")) {
723-
List<String> values = (List<String>) vendorExtensions.get("x-enum-descriptions");
724-
int size = Math.min(enumVars.size(), values.size());
725-
for (int i = 0; i < size; i++) {
726-
enumVars.get(i).put("enumDescription", values.get(i));
736+
Object extensionValue = vendorExtensions.get("x-enum-descriptions");
737+
if (extensionValue instanceof List) {
738+
List<String> values = (List<String>) extensionValue;
739+
int size = Math.min(enumVars.size(), values.size());
740+
for (int i = 0; i < size; i++) {
741+
enumVars.get(i).put("enumDescription", values.get(i));
742+
}
743+
} else if (extensionValue instanceof Map) {
744+
Map<String, String> valueMap = (Map<String, String>) extensionValue;
745+
for (Map<String, Object> enumVar : enumVars) {
746+
String enumValue = (String) enumVar.get("value");
747+
for (Map.Entry<String, String> entry : valueMap.entrySet()) {
748+
if (toEnumValue(entry.getKey(), dataType).equals(enumValue)) {
749+
enumVar.put("enumDescription", entry.getValue());
750+
break;
751+
}
752+
}
753+
}
727754
}
728755
}
729756
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,26 @@ public void postProcessModelsEnumWithExtension() {
995995
assertEquals("This is a cat", enumVars.get(1).getOrDefault("enumDescription", ""));
996996
}
997997

998+
@Test
999+
public void postProcessModelsEnumWithMapExtension() {
1000+
final DefaultCodegen codegen = new DefaultCodegen();
1001+
ModelsMap objs = codegenModelWithXEnumVarNameAsMap();
1002+
CodegenModel cm = objs.getModels().get(0).getModel();
1003+
1004+
codegen.postProcessModelsEnum(objs);
1005+
1006+
List<Map<String, Object>> enumVars = (List<Map<String, Object>>) cm.getAllowableValues().get("enumVars");
1007+
Assertions.assertNotNull(enumVars);
1008+
Assertions.assertNotNull(enumVars.get(0));
1009+
assertEquals("DOGVAR", enumVars.get(0).getOrDefault("name", ""));
1010+
assertEquals("\"dog\"", enumVars.get(0).getOrDefault("value", ""));
1011+
assertEquals("This is a dog", enumVars.get(0).getOrDefault("enumDescription", ""));
1012+
Assertions.assertNotNull(enumVars.get(1));
1013+
assertEquals("CATVAR", enumVars.get(1).getOrDefault("name", ""));
1014+
assertEquals("\"cat\"", enumVars.get(1).getOrDefault("value", ""));
1015+
assertEquals("This is a cat", enumVars.get(1).getOrDefault("enumDescription", ""));
1016+
}
1017+
9981018
@Test
9991019
public void testExample1() {
10001020
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/examples.yaml");
@@ -2314,6 +2334,27 @@ private ModelsMap codegenModelWithXEnumVarName() {
23142334
return TestUtils.createCodegenModelWrapper(cm);
23152335
}
23162336

2337+
private ModelsMap codegenModelWithXEnumVarNameAsMap() {
2338+
final CodegenModel cm = new CodegenModel();
2339+
cm.isEnum = true;
2340+
final HashMap<String, Object> allowableValues = new HashMap<>();
2341+
allowableValues.put("values", Arrays.asList("dog", "cat"));
2342+
cm.setAllowableValues(allowableValues);
2343+
cm.dataType = "String";
2344+
Map<String, String> aliases = new LinkedHashMap<>();
2345+
aliases.put("dog", "DOGVAR");
2346+
aliases.put("cat", "CATVAR");
2347+
Map<String, String> descriptions = new LinkedHashMap<>();
2348+
descriptions.put("dog", "This is a dog");
2349+
descriptions.put("cat", "This is a cat");
2350+
Map<String, Object> extensions = new HashMap<>();
2351+
extensions.put("x-enum-varnames", aliases);
2352+
extensions.put("x-enum-descriptions", descriptions);
2353+
cm.setVendorExtensions(extensions);
2354+
cm.setVars(Collections.emptyList());
2355+
return TestUtils.createCodegenModelWrapper(cm);
2356+
}
2357+
23172358
@Test
23182359
public void objectQueryParamIdentifyAsObject() {
23192360
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/objectQueryParam.yaml");

0 commit comments

Comments
 (0)