Skip to content

Commit

Permalink
feat(client): update jackson client generation to always annotate all…
Browse files Browse the repository at this point in the history
… fields (#1976)

### 📝 Description
Update Jackson client generation logic to always annotate all fields
with @get:JsonProperty.
This is a workaround to Jackson limitations due to its reliance on
reflections to find getters/setters following JavaBean naming
conventions.

Simple mutation:
``` graphql
mutation CreateIssuedInvoice($input: IssuedInvoiceInput!) {
    CreateIssuedInvoice(IssuedInvoice: $input) {
        ID
        Stav
        CisloDokladu
    }
}
```

Genarated before change:
```kotlin
public const val CREATE_ISSUED_INVOICE: String =
    "mutation CreateIssuedInvoice(${'$'}input: IssuedInvoiceInput!) {\n    CreateIssuedInvoice(IssuedInvoice: ${'$'}input) {\n        ID\n        Stav\n        CisloDokladu\n    }\n}"

@generated
public class CreateIssuedInvoice(
  override val variables: CreateIssuedInvoice.Variables,
) : GraphQLClientRequest<CreateIssuedInvoice.Result> {
  override val query: String = CREATE_ISSUED_INVOICE

  override val operationName: String = "CreateIssuedInvoice"

  override fun responseType(): KClass<CreateIssuedInvoice.Result> =
      CreateIssuedInvoice.Result::class

  @generated
  public data class Variables(
    @get:JsonProperty(value = "input")
    public val input: IssuedInvoiceInput,
  )

  /**
   * Dotazy pro zápis, editaci a mazání S5 objektů
   */
  @generated
  public data class Result(
    /**
     * Faktura vydaná (zápis)
     */
    public val CreateIssuedInvoice: IssuedInvoice? = null,
  )
}
```
Genareted after change:
```kotlin
public const val CREATE_ISSUED_INVOICE: String =
    "mutation CreateIssuedInvoice(${'$'}input: IssuedInvoiceInput!) {\n    CreateIssuedInvoice(IssuedInvoice: ${'$'}input) {\n        ID\n        Stav\n        CisloDokladu\n    }\n}"

@generated
public class CreateIssuedInvoice(
  override val variables: CreateIssuedInvoice.Variables,
) : GraphQLClientRequest<CreateIssuedInvoice.Result> {
  override val query: String = CREATE_ISSUED_INVOICE

  override val operationName: String = "CreateIssuedInvoice"

  override fun responseType(): KClass<CreateIssuedInvoice.Result> =
      CreateIssuedInvoice.Result::class

  @generated
  public data class Variables(
    @get:JsonProperty(value = "input")
    public val input: IssuedInvoiceInput,
  )

  /**
   * Dotazy pro zápis, editaci a mazání S5 objektů
   */
  @generated
  public data class Result(
    /**
     * Faktura vydaná (zápis)
     */
    @get:JsonProperty("CreateIssuedInvoice")
    public val CreateIssuedInvoice: IssuedInvoice? = null,
  )
}
```

data class IssuedInvoice **before** change:
```kotlin
@generated
public data class IssuedInvoice(
  /**
   * ID
   */
  @JsonSerialize(converter = UUIDToAnyConverter::class)
  @JsonDeserialize(converter = AnyToUUIDConverter::class)
  public val ID: UUID? = null,
  /**
   * Stav
   */
  public val Stav: Int? = null,
  /**
   * Číslo dokladu
   */
  public val CisloDokladu: String? = null,
)
```

data class IssuedInvoice **after** change:
```kotlin
@generated
public data class IssuedInvoice(
  /**
   * ID
   */
  @JsonSerialize(converter = UUIDToAnyConverter::class)
  @JsonDeserialize(converter = AnyToUUIDConverter::class)
  @get:JsonProperty("ID")
  public val ID: UUID? = null,
  /**
   * Stav
   */
  @get:JsonProperty("Stav")
  public val Stav: Int? = null,
  /**
   * Číslo dokladu
   */
  @get:JsonProperty("CisloDokladu")
  public val CisloDokladu: String? = null,
)
```

### 🔗 Related Issues
https://kotlinlang.slack.com/archives/CQLNT7B29/p1717655752084109
  • Loading branch information
SalyczeQ authored Jun 13, 2024
1 parent bce5bc4 commit 60879c5
Show file tree
Hide file tree
Showing 85 changed files with 303 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
package com.expediagroup.graphql.plugin.client.generator.types

import com.expediagroup.graphql.plugin.client.generator.GraphQLClientGeneratorContext
import com.expediagroup.graphql.plugin.client.generator.GraphQLSerializer
import com.expediagroup.graphql.plugin.client.generator.ScalarConverterInfo
import com.expediagroup.graphql.plugin.client.generator.exceptions.DeprecatedFieldsSelectedException
import com.expediagroup.graphql.plugin.client.generator.exceptions.InvalidSelectionSetException
import com.expediagroup.graphql.plugin.client.generator.exceptions.MissingArgumentException
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.squareup.kotlinpoet.AnnotationSpec
Expand Down Expand Up @@ -96,6 +98,16 @@ internal fun generatePropertySpecs(
fieldDefinition.description?.content?.let { kdoc ->
propertySpecBuilder.addKdoc("%L", kdoc)
}
if (context.serializer == GraphQLSerializer.JACKSON) {
// always add @get:JsonProperty annotation as a workaround to Jackson limitations
// related to JavaBean naming conventions
propertySpecBuilder.addAnnotation(
AnnotationSpec.builder(JsonProperty::class)
.useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
.addMember("value = \"$fieldName\"")
.build()
)
}
propertySpecBuilder.build()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.expediagroup.graphql.generated

import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.Boolean
import kotlin.String
import kotlin.reflect.KClass
Expand All @@ -22,10 +23,12 @@ public class AliasQuery : GraphQLClientRequest<AliasQuery.Result> {
/**
* Query that accepts some input arguments
*/
@get:JsonProperty(value = "first")
public val first: Boolean,
/**
* Query that accepts some input arguments
*/
@get:JsonProperty(value = "second")
public val second: Boolean,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.expediagroup.graphql.generated.aliasnestedquery.ComplexObject
import com.expediagroup.graphql.generated.aliasnestedquery.ComplexObject2
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String
import kotlin.reflect.KClass

Expand All @@ -23,10 +24,12 @@ public class AliasNestedQuery : GraphQLClientRequest<AliasNestedQuery.Result> {
/**
* Query returning an object that references another object
*/
@get:JsonProperty(value = "first")
public val first: ComplexObject,
/**
* Query returning an object that references another object
*/
@get:JsonProperty(value = "second")
public val second: ComplexObject2,
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.aliasnestedquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String

/**
Expand All @@ -13,5 +14,6 @@ public data class ComplexObject(
/**
* Some object name
*/
@get:JsonProperty(value = "nameA")
public val nameA: String,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.aliasnestedquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String

/**
Expand All @@ -13,5 +14,6 @@ public data class ComplexObject2(
/**
* Some object name
*/
@get:JsonProperty(value = "nameB")
public val nameB: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.expediagroup.graphql.generated
import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.expediagroup.graphql.generated.documentationquery.DocObject
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String
import kotlin.reflect.KClass

Expand All @@ -22,6 +23,7 @@ public class DocumentationQuery : GraphQLClientRequest<DocumentationQuery.Result
/**
* Query to test doc strings
*/
@get:JsonProperty(value = "docQuery")
public val docQuery: DocObject,
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.documentationquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.Int

/**
Expand All @@ -11,5 +12,6 @@ public data class DocObject(
/**
* An id with a comment containing % and $ as well
*/
@get:JsonProperty(value = "id")
public val id: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ public class IncludeSkipDirectivesQuery(
/**
* Query that returns enum value
*/
@get:JsonProperty(value = "enumQuery")
public val enumQuery: CustomEnum? = null,
/**
* Query that returns wrapper object with all supported scalar types
*/
@get:JsonProperty(value = "scalarQuery")
public val scalarQuery: ScalarWrapper? = null,
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.includeskipdirectivesquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.Int

/**
Expand All @@ -11,5 +12,6 @@ public data class ScalarWrapper(
/**
* A signed 32-bit nullable integer value
*/
@get:JsonProperty(value = "count")
public val count: Int? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.expediagroup.graphql.generated

import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.Boolean
import kotlin.String
import kotlin.reflect.KClass
Expand All @@ -23,6 +24,7 @@ public class HardCodedInputQuery : GraphQLClientRequest<HardCodedInputQuery.Resu
/**
* Query that accepts some input arguments
*/
@get:JsonProperty(value = "inputObjectQuery")
public val inputObjectQuery: Boolean,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class InputListQuery(
/**
* Query accepting list input
*/
@get:JsonProperty(value = "listInputQuery")
public val listInputQuery: String? = null,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class SelfReferencingInputQuery(
/**
* Query that accepts self referencing input object
*/
@get:JsonProperty(value = "complexInputObjectQuery")
public val complexInputObjectQuery: Boolean,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.expediagroup.graphql.generated.differentselectionsetquery.BasicInterface
import com.expediagroup.graphql.generated.differentselectionsetquery.BasicInterface2
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String
import kotlin.reflect.KClass

Expand All @@ -24,10 +25,12 @@ public class DifferentSelectionSetQuery : GraphQLClientRequest<DifferentSelectio
/**
* Query returning an interface
*/
@get:JsonProperty(value = "first")
public val first: BasicInterface,
/**
* Query returning an interface
*/
@get:JsonProperty(value = "second")
public val second: BasicInterface2,
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.differentselectionsetquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import com.fasterxml.jackson.`annotation`.JsonSubTypes
import com.fasterxml.jackson.`annotation`.JsonTypeInfo
import com.fasterxml.jackson.`annotation`.JsonTypeInfo.As.PROPERTY
Expand All @@ -27,11 +28,13 @@ public interface BasicInterface {
/**
* Unique identifier of an interface
*/
@get:JsonProperty(value = "id")
public val id: Int

/**
* Name field
*/
@get:JsonProperty(value = "name")
public val name: String
}

Expand All @@ -43,14 +46,17 @@ public data class FirstInterfaceImplementation(
/**
* Unique identifier of the first implementation
*/
@get:JsonProperty(value = "id")
override val id: Int,
/**
* Name of the first implementation
*/
@get:JsonProperty(value = "name")
override val name: String,
/**
* Custom field integer value
*/
@get:JsonProperty(value = "intValue")
public val intValue: Int,
) : BasicInterface

Expand All @@ -62,14 +68,17 @@ public data class SecondInterfaceImplementation(
/**
* Unique identifier of the second implementation
*/
@get:JsonProperty(value = "id")
override val id: Int,
/**
* Name of the second implementation
*/
@get:JsonProperty(value = "name")
override val name: String,
/**
* Custom field float value
*/
@get:JsonProperty(value = "floatValue")
public val floatValue: Double,
) : BasicInterface

Expand All @@ -82,9 +91,11 @@ public data class DefaultBasicInterfaceImplementation(
/**
* Unique identifier of an interface
*/
@get:JsonProperty(value = "id")
override val id: Int,
/**
* Name field
*/
@get:JsonProperty(value = "name")
override val name: String,
) : BasicInterface
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.expediagroup.graphql.generated.differentselectionsetquery

import com.expediagroup.graphql.client.Generated
import com.fasterxml.jackson.`annotation`.JsonProperty
import com.fasterxml.jackson.`annotation`.JsonSubTypes
import com.fasterxml.jackson.`annotation`.JsonTypeInfo
import com.fasterxml.jackson.`annotation`.JsonTypeInfo.As.PROPERTY
Expand All @@ -27,6 +28,7 @@ public interface BasicInterface2 {
/**
* Name field
*/
@get:JsonProperty(value = "name")
public val name: String
}

Expand All @@ -38,10 +40,12 @@ public data class FirstInterfaceImplementation2(
/**
* Name of the first implementation
*/
@get:JsonProperty(value = "name")
override val name: String,
/**
* Custom field integer value
*/
@get:JsonProperty(value = "intValue")
public val intValue: Int,
) : BasicInterface2

Expand All @@ -53,10 +57,12 @@ public data class SecondInterfaceImplementation2(
/**
* Name of the second implementation
*/
@get:JsonProperty(value = "name")
override val name: String,
/**
* Custom field float value
*/
@get:JsonProperty(value = "floatValue")
public val floatValue: Double,
) : BasicInterface2

Expand All @@ -69,5 +75,6 @@ public data class DefaultBasicInterface2Implementation(
/**
* Name field
*/
@get:JsonProperty(value = "name")
override val name: String,
) : BasicInterface2
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.expediagroup.graphql.client.Generated
import com.expediagroup.graphql.client.types.GraphQLClientRequest
import com.expediagroup.graphql.generated.differentselectionsetquery.BasicInterface
import com.expediagroup.graphql.generated.differentselectionsetquery.BasicInterface2
import com.fasterxml.jackson.`annotation`.JsonProperty
import kotlin.String
import kotlin.reflect.KClass

Expand All @@ -24,10 +25,12 @@ public class DifferentSelectionSetQuery : GraphQLClientRequest<DifferentSelectio
/**
* Query returning an interface
*/
@get:JsonProperty(value = "first")
public val first: BasicInterface,
/**
* Query returning an interface
*/
@get:JsonProperty(value = "second")
public val second: BasicInterface2,
)
}
Loading

0 comments on commit 60879c5

Please sign in to comment.