Skip to content

Commit 11221eb

Browse files
wiebrenclaude
andauthored
[kotlin] fix: enumUnknownDefaultCase's moshi fallback adapters break nullable enum fields (#24894)
* [kotlin] fix: make the enumUnknownDefaultCase moshi fallback adapters null-safe SerializerHelper registers a moshi EnumJsonAdapter with withUnknownFallback per enum, but EnumJsonAdapter is not null-safe and it is registered bare: any model with a nullable enum property throws "value was null! Wrap in .nullSafe() to write nullable values" on a null value, reading and writing alike. The flag traded unknown-value tolerance for a regression on every optional enum field. Append .nullSafe() in both branches. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GcwZ1arjLZNpetHz2a3TJz * test: [kotlin] shorten the null-safe adapter test comment Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 7bee48f commit 11221eb

3 files changed

Lines changed: 34 additions & 7 deletions

File tree

‎modules/openapi-generator/src/main/resources/kotlin-client/jvm-common/infrastructure/SerializerHelper.kt.mustache‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import com.squareup.moshi.adapters.EnumJsonAdapter
1919
{{#enumVars}}
2020
{{#-last}}
2121
.add({{modelPackage}}.{{classname}}::class.java, EnumJsonAdapter.create({{modelPackage}}.{{classname}}::class.java)
22-
.withUnknownFallback({{modelPackage}}.{{classname}}.{{&name}}))
22+
.withUnknownFallback({{modelPackage}}.{{classname}}.{{&name}}).nullSafe())
2323
{{/-last}}
2424
{{/enumVars}}
2525
{{/allowableValues}}
@@ -33,7 +33,7 @@ import com.squareup.moshi.adapters.EnumJsonAdapter
3333
{{#enumVars}}
3434
{{#-last}}
3535
.add({{modelPackage}}.{{classname}}.{{{nameInPascalCase}}}::class.java, EnumJsonAdapter.create({{modelPackage}}.{{classname}}.{{{nameInPascalCase}}}::class.java)
36-
.withUnknownFallback({{modelPackage}}.{{classname}}.{{{nameInPascalCase}}}.{{&name}}))
36+
.withUnknownFallback({{modelPackage}}.{{classname}}.{{{nameInPascalCase}}}.{{&name}}).nullSafe())
3737
{{/-last}}
3838
{{/enumVars}}
3939
{{/allowableValues}}

‎modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenModelTest.java‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,33 @@ public void testJacksonEnumsExposeDecodeOrNullHelper() throws IOException {
990990
"Expected exactly one @JsonCreator annotation in the generated enum, found " + jsonCreatorCount);
991991
}
992992

993+
@Test
994+
public void testMoshiEnumUnknownDefaultCaseAdaptersAreNullSafe() throws IOException {
995+
File output = Files.createTempDirectory("test").toFile();
996+
output.deleteOnExit();
997+
998+
final CodegenConfigurator configurator = new CodegenConfigurator()
999+
.setGeneratorName(KOTLIN_GENERATOR)
1000+
.setLibrary("jvm-okhttp4")
1001+
.setAdditionalProperties(new HashMap<>() {{
1002+
put(CodegenConstants.SERIALIZATION_LIBRARY, "moshi");
1003+
put(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, "true");
1004+
}})
1005+
.setInputSpec("src/test/resources/3_0/enum.yaml")
1006+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
1007+
1008+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
1009+
DefaultGenerator generator = new DefaultGenerator();
1010+
1011+
generator.opts(clientOptInput).generate();
1012+
1013+
final Path helperKt = Paths.get(output + "/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt");
1014+
1015+
// EnumJsonAdapter is not null-safe, so every registered fallback adapter must be wrapped
1016+
TestUtils.assertFileContains(helperKt, ".nullSafe())");
1017+
TestUtils.assertFileNotContains(helperKt, "unknown_default_open_api))");
1018+
}
1019+
9931020
@Test
9941021
public void testJacksonEnumsWithUnknownDefaultCase() throws IOException {
9951022
File output = Files.createTempDirectory("test").toFile();

‎samples/client/petstore/kotlin-enum-default-value/src/main/kotlin/org/openapitools/client/infrastructure/SerializerHelper.kt‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ object SerializerHelper {
77
fun addEnumUnknownDefaultCase(moshiBuilder: Moshi.Builder): Moshi.Builder {
88
return moshiBuilder
99
.add(org.openapitools.client.models.ComplexEnum::class.java, EnumJsonAdapter.create(org.openapitools.client.models.ComplexEnum::class.java)
10-
.withUnknownFallback(org.openapitools.client.models.ComplexEnum.unknown_default_open_api))
10+
.withUnknownFallback(org.openapitools.client.models.ComplexEnum.unknown_default_open_api).nullSafe())
1111
.add(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName::class.java, EnumJsonAdapter.create(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName::class.java)
12-
.withUnknownFallback(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName.unknown_default_open_api))
12+
.withUnknownFallback(org.openapitools.client.models.ModelWithEnumPropertyHavingDefault.PropertyName.unknown_default_open_api).nullSafe())
1313
.add(org.openapitools.client.models.PropertyOfDay.DaysOfWeek::class.java, EnumJsonAdapter.create(org.openapitools.client.models.PropertyOfDay.DaysOfWeek::class.java)
14-
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.DaysOfWeek.unknown_default_open_api))
14+
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.DaysOfWeek.unknown_default_open_api).nullSafe())
1515
.add(org.openapitools.client.models.PropertyOfDay.MonthOfYear::class.java, EnumJsonAdapter.create(org.openapitools.client.models.PropertyOfDay.MonthOfYear::class.java)
16-
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.MonthOfYear.unknown_default_open_api))
16+
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.MonthOfYear.unknown_default_open_api).nullSafe())
1717
.add(org.openapitools.client.models.PropertyOfDay.HolidayTypes::class.java, EnumJsonAdapter.create(org.openapitools.client.models.PropertyOfDay.HolidayTypes::class.java)
18-
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.HolidayTypes.unknown_default_open_api))
18+
.withUnknownFallback(org.openapitools.client.models.PropertyOfDay.HolidayTypes.unknown_default_open_api).nullSafe())
1919
}
2020
}

0 commit comments

Comments
 (0)