Skip to content

Commit 3f84e5b

Browse files
committed
Remove @JsonCreator annotation to prevent conflicting creators exception from Jackson 2.21+
1 parent d7a9bf3 commit 3f84e5b

File tree

26 files changed

+131
-48
lines changed

26 files changed

+131
-48
lines changed

graphql-dgs-codegen-core/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ dependencies {
4141
testImplementation 'com.google.guava:guava:33.4.+'
4242
testImplementation 'com.google.testing.compile:compile-testing:0.+'
4343
testImplementation 'org.jetbrains.kotlin:kotlin-compiler'
44+
45+
integTestImplementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
4446
}
4547

4648
application {

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/Kotlin2CodeGenTest.kt

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818

1919
package com.netflix.graphql.dgs.codegen
2020

21+
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
2122
import org.assertj.core.api.Assertions.assertThat
2223
import org.assertj.core.api.Assertions.fail
2324
import org.junit.jupiter.api.Test
2425
import org.junit.jupiter.params.ParameterizedTest
2526
import org.junit.jupiter.params.provider.MethodSource
27+
import java.net.URLClassLoader
2628
import java.nio.file.Files
2729
import java.nio.file.Path
2830
import java.nio.file.Paths
@@ -35,6 +37,7 @@ import kotlin.io.path.readText
3537
class Kotlin2CodeGenTest {
3638
// set this to true to update all expected outputs instead of running tests
3739
private val updateExpected = false
40+
private val objectMapper = jacksonObjectMapper()
3841

3942
@ParameterizedTest
4043
@MethodSource("listTestsToRun")
@@ -160,6 +163,109 @@ class Kotlin2CodeGenTest {
160163
assertCompilesKotlin(codeGenResult)
161164
}
162165

166+
@Test
167+
fun `Jackson should deserialize input type with all optional fields without @JsonCreator annotation`() {
168+
val schema =
169+
"""
170+
input PersonInput {
171+
name: String
172+
age: Int
173+
email: String
174+
}
175+
""".trimIndent()
176+
177+
val result =
178+
CodeGen(
179+
CodeGenConfig(
180+
schemas = setOf(schema),
181+
packageName = "com.netflix.test.alloptional",
182+
language = Language.KOTLIN,
183+
generateKotlinNullableClasses = true,
184+
generateKotlinClosureProjections = true,
185+
),
186+
).generate()
187+
188+
val buildDir = assertCompilesKotlin(result)
189+
val classLoader = URLClassLoader(arrayOf(buildDir.toUri().toURL()), this.javaClass.classLoader)
190+
val inputClass = classLoader.loadClass("com.netflix.test.alloptional.types.PersonInput")
191+
192+
val json = """{"name": "John", "age": 30, "email": "john@example.com"}"""
193+
val instance = objectMapper.readValue(json, inputClass)
194+
assertThat(instance).isNotNull
195+
}
196+
197+
@Test
198+
fun `Jackson should deserialize input type with required field`() {
199+
val schema =
200+
"""
201+
input PersonInput {
202+
name: String!
203+
age: Int
204+
email: String
205+
}
206+
""".trimIndent()
207+
208+
val result =
209+
CodeGen(
210+
CodeGenConfig(
211+
schemas = setOf(schema),
212+
packageName = "com.netflix.test.withrequired",
213+
language = Language.KOTLIN,
214+
generateKotlinNullableClasses = true,
215+
generateKotlinClosureProjections = true,
216+
),
217+
).generate()
218+
219+
val buildDir = assertCompilesKotlin(result)
220+
val classLoader = URLClassLoader(arrayOf(buildDir.toUri().toURL()), this.javaClass.classLoader)
221+
val inputClass = classLoader.loadClass("com.netflix.test.withrequired.types.PersonInput")
222+
223+
// Test runtime Jackson deserialization
224+
val json = """{"name": "John", "age": 30, "email": "john@example.com"}"""
225+
val instance = objectMapper.readValue(json, inputClass)
226+
assertThat(instance).isNotNull
227+
228+
val nameField = inputClass.getDeclaredField("name")
229+
nameField.isAccessible = true
230+
assertThat(nameField.get(instance)).isEqualTo("John")
231+
}
232+
233+
@Test
234+
fun `Input type with explicit defaults should deserialize without conflicting creators error`() {
235+
val schema =
236+
"""
237+
input PersonInput {
238+
name: String! = "Unknown"
239+
age: Int! = 0
240+
active: Boolean! = true
241+
}
242+
""".trimIndent()
243+
244+
val result =
245+
CodeGen(
246+
CodeGenConfig(
247+
schemas = setOf(schema),
248+
packageName = "com.netflix.test.alldefaults",
249+
language = Language.KOTLIN,
250+
generateKotlinNullableClasses = true,
251+
generateKotlinClosureProjections = true,
252+
),
253+
).generate()
254+
255+
val buildDir = assertCompilesKotlin(result)
256+
val classLoader = URLClassLoader(arrayOf(buildDir.toUri().toURL()), this.javaClass.classLoader)
257+
val inputClass = classLoader.loadClass("com.netflix.test.alldefaults.types.PersonInput")
258+
259+
val json = """{"name": "John", "age": 30, "active": false}"""
260+
261+
val instance = objectMapper.readValue(json, inputClass)
262+
assertThat(instance).isNotNull
263+
264+
val nameField = inputClass.getDeclaredField("name")
265+
nameField.isAccessible = true
266+
assertThat(nameField.get(instance)).isEqualTo("John")
267+
}
268+
163269
companion object {
164270
@Suppress("unused")
165271
@JvmStatic

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/constantsForInputTypes/expected/types/PersonFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.netflix.graphql.dgs.codegen.cases.constantsForInputTypes.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
76
import kotlin.Pair
87
import kotlin.String
98
import kotlin.collections.List
109

11-
public data class PersonFilter @JsonCreator constructor(
10+
public data class PersonFilter(
1211
@JsonProperty("email")
1312
public val email: String? = default<PersonFilter, String?>("email", null),
1413
) : GraphQLInput() {

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/constantsWithExtendedInputTypes/expected/types/PersonFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.netflix.graphql.dgs.codegen.cases.constantsWithExtendedInputTypes.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
@@ -9,7 +8,7 @@ import kotlin.Pair
98
import kotlin.String
109
import kotlin.collections.List
1110

12-
public data class PersonFilter @JsonCreator constructor(
11+
public data class PersonFilter(
1312
@JsonProperty("email")
1413
public val email: String? = default<PersonFilter, String?>("email", null),
1514
@JsonProperty("birthYear")

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/dataClassDocs/expected/types/MovieFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.netflix.graphql.dgs.codegen.cases.dataClassDocs.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
@@ -13,7 +12,7 @@ import kotlin.collections.List
1312
*
1413
* It takes a title and such.
1514
*/
16-
public data class MovieFilter @JsonCreator constructor(
15+
public data class MovieFilter(
1716
@JsonProperty("titleFilter")
1817
public val titleFilter: String? = default<MovieFilter, String?>("titleFilter", null),
1918
) : GraphQLInput() {

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/dataClassFieldDocs/expected/types/MovieFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.netflix.graphql.dgs.codegen.cases.dataClassFieldDocs.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
76
import kotlin.Pair
87
import kotlin.String
98
import kotlin.collections.List
109

11-
public data class MovieFilter @JsonCreator constructor(
10+
public data class MovieFilter(
1211
@JsonProperty("titleFilter")
1312
public val titleFilter: String? = default<MovieFilter, String?>("titleFilter", null),
1413
) : GraphQLInput() {

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/input/expected/types/MovieFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.netflix.graphql.dgs.codegen.cases.input.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
76
import kotlin.Pair
87
import kotlin.String
98
import kotlin.collections.List
109

11-
public data class MovieFilter @JsonCreator constructor(
10+
public data class MovieFilter(
1211
@JsonProperty("genre")
1312
public val genre: String? = default<MovieFilter, String?>("genre", null),
1413
) : GraphQLInput() {

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/inputWithDefaultBigDecimal/expected/types/OrderFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.netflix.graphql.dgs.codegen.cases.inputWithDefaultBigDecimal.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import java.math.BigDecimal
@@ -9,7 +8,7 @@ import kotlin.Pair
98
import kotlin.String
109
import kotlin.collections.List
1110

12-
public data class OrderFilter @JsonCreator constructor(
11+
public data class OrderFilter(
1312
@JsonProperty("min")
1413
public val min: BigDecimal = default<OrderFilter, BigDecimal>("min", java.math.BigDecimal("1.1")),
1514
@JsonProperty("avg")

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/inputWithDefaultCurrency/expected/types/OrderFilter.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.netflix.graphql.dgs.codegen.cases.inputWithDefaultCurrency.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import java.util.Currency
@@ -9,7 +8,7 @@ import kotlin.Pair
98
import kotlin.String
109
import kotlin.collections.List
1110

12-
public data class OrderFilter @JsonCreator constructor(
11+
public data class OrderFilter(
1312
@JsonProperty("value")
1413
public val `value`: Currency = default<OrderFilter, Currency>("value",
1514
java.util.Currency.getInstance("USD")),

graphql-dgs-codegen-core/src/integTest/kotlin/com/netflix/graphql/dgs/codegen/cases/inputWithDefaultEnumValueForArray/expected/types/SomeType.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.netflix.graphql.dgs.codegen.cases.inputWithDefaultEnumValueForArray.expected.types
22

3-
import com.fasterxml.jackson.`annotation`.JsonCreator
43
import com.fasterxml.jackson.`annotation`.JsonProperty
54
import com.netflix.graphql.dgs.codegen.GraphQLInput
65
import kotlin.Any
76
import kotlin.Pair
87
import kotlin.String
98
import kotlin.collections.List
109

11-
public data class SomeType @JsonCreator constructor(
10+
public data class SomeType(
1211
@JsonProperty("colors")
1312
public val colors: List<Color?>? = default<SomeType, List<Color?>?>("colors",
1413
listOf(com.netflix.graphql.dgs.codegen.cases.inputWithDefaultEnumValueForArray.expected.types.Color.red)),

0 commit comments

Comments
 (0)