Parsing of response to generated query to generated type fails when encountering an enum
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 217
- Forks
- 116
- PR merge metrics
- No merged PRs in 30d
Description
I use the schema found here (also attached as txt)
schema.txt
Using codegen, I generate this request:
query {
site {
settings {
url {
vanityUrl
}
}
products(first: 10) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
entityId
name
plainTextDescription(characterLimit: 1024)
brand {
name
}
availabilityV2 {
status
}
inventory {
hasVariantInventory
aggregated {
availableToSell
}
}
path
categories(first: 10) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
name
}
}
}
images(first: 50) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
urlOriginal
altText
}
}
}
prices {
price {
value
currencyCode
}
basePrice {
value
currencyCode
}
salePrice {
value
currencyCode
}
}
productOptions(first: 3) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
displayName
... on MultipleChoiceOption {
__typename
values {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
label
}
}
}
}
}
}
}
variants(first: 200) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
inventory {
aggregated {
availableToSell
}
}
entityId
productOptions(first: 3) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
entityId
displayName
... on MultipleChoiceOption {
__typename
values {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
label
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
I get this response:
{
"data" : {
"site" : {
"settings" : {
"url" : {
"vanityUrl" : "https://shop.soapboxus.com"
}
},
"products" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"entityId" : 175,
"name" : "Tide ReLoad Compatible Detergent",
"plainTextDescription" : "\n\nThis Box Contains\nOne Tide ReLoad™ tray and Detergent\nTide ReLoad™ tray works with multiple types of detergent, shipped directly from us with free shipping. Just choose the type of Tide you like best – Tide PODS Original, Tide PODS Spring Meadow, or Tide Eco-Box Original. Please note that Tide ReLoad™ tray will not work with Tide products purchased elsewhere.\n",
"brand" : null,
"availabilityV2" : {
"status" : "Available"
},
"inventory" : {
"hasVariantInventory" : false,
"aggregated" : null
},
"path" : "/tide-smart-tray-detergent/",
"categories" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : null
},
"edges" : [ ]
},
"images" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjY="
},
"edges" : [ {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/800/Image_1_-_Delivered__03950.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/802/Image_2_-_Free_Shipping__53500.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/815/Image_3_-_Never_run_out_copy__63238.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/799/Image_4_-_Cancel_Anytime__26398.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/798/Image_5_-_Set_up__06965.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/803/Image_6_-_Skip_the_trip_to_the_store__76617.1633532989.jpg",
"altText" : ""
}
}, {
"node" : {
"urlOriginal" : "https://cdn11.bigcommerce.com/s-v1a6036467/images/stencil/original/products/175/801/Image_7_-_Comes_with__54036.1633532989.jpg",
"altText" : ""
}
} ]
},
"prices" : {
"price" : {
"value" : 19.99,
"currencyCode" : "USD"
},
"basePrice" : {
"value" : 19.99,
"currencyCode" : "USD"
},
"salePrice" : null
},
"productOptions" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"displayName" : "Your detergent selection",
"__typename" : "MultipleChoiceOption",
"values" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjI="
},
"edges" : [ {
"node" : {
"label" : "Original"
}
}, {
"node" : {
"label" : "Spring Meadow"
}
}, {
"node" : {
"label" : "Tide Eco Box"
}
} ]
}
}
} ]
},
"variants" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjI="
},
"edges" : [ {
"node" : {
"inventory" : {
"aggregated" : null
},
"entityId" : 170,
"productOptions" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"entityId" : 21,
"displayName" : "Your detergent selection",
"__typename" : "MultipleChoiceOption",
"values" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"label" : "Original"
}
} ]
}
}
} ]
}
}
}, {
"node" : {
"inventory" : {
"aggregated" : null
},
"entityId" : 171,
"productOptions" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"entityId" : 21,
"displayName" : "Your detergent selection",
"__typename" : "MultipleChoiceOption",
"values" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"label" : "Spring Meadow"
}
} ]
}
}
} ]
}
}
}, {
"node" : {
"inventory" : {
"aggregated" : null
},
"entityId" : 172,
"productOptions" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"entityId" : 21,
"displayName" : "Your detergent selection",
"__typename" : "MultipleChoiceOption",
"values" : {
"pageInfo" : {
"hasNextPage" : false,
"endCursor" : "YXJyYXljb25uZWN0aW9uOjA="
},
"edges" : [ {
"node" : {
"label" : "Tide Eco Box"
}
} ]
}
}
} ]
}
}
} ]
}
}
} ]
}
}
}
}
I then attempt to parse the response to the proper generated type
GraphQLResponse graphQLResponse =
graphQLClient.executeQuery(graphQLQueryRequest.serialize());
Optional<JsonNode> dataOptional =
Optional.of(objectMapper.readTree(graphQLResponse.getJson()));
System.out.println(dataOptional.get().toPrettyString());
Optional<JsonNode> siteOptional =
dataOptional.map(json -> json.get("data")).map(data -> data.get("site"));
if (siteOptional.isEmpty()) {
throw new NullPointerException();
}
com.attentivemobile.syncprocessor.model.bigcommerce.types.Site site =
objectMapper.treeToValue(siteOptional.get(), Site.class);
then I get this
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.attentivemobile.syncprocessor.model.bigcommerce.types.ProductAvailability]: missing type id property '__typename' (for POJO property 'availabilityV2')
at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.attentivemobile.syncprocessor.model.bigcommerce.types.Site["products"]->com.attentivemobile.syncprocessor.model.bigcommerce.types.ProductConnection["edges"]->java.util.ArrayList[0]->com.attentivemobile.syncprocessor.model.bigcommerce.types.ProductEdge["node"]->com.attentivemobile.syncprocessor.model.bigcommerce.types.Product["availabilityV2"])
I'm using the following configuration via the community maven port
<plugin>
<groupId>io.github.deweyjose</groupId>
<artifactId>graphqlcodegen-maven-plugin</artifactId>
<version>1.16</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaPaths>
<param>
src/main/resources/api/bigcommerce/schema.graphql
</param>
</schemaPaths>
<packageName>com.attentivemobile.syncprocessor.model.bigcommerce</packageName>
<!-- Required because scalars chosen by BigCommerce impose graphql-java scalar mappings-->
<typeMapping>
<BigDecimal>java.math.BigDecimal</BigDecimal>
<Long>java.lang.Long</Long>
<PageInfo>
com.attentivemobile.syncprocessor.model.bigcommerce.GraphQLConnection.PageInfo
</PageInfo>
</typeMapping>
<generateClient>true</generateClient>
<includeQueries>site</includeQueries>
<includeSubscriptions>[]</includeSubscriptions>
<includeMutations>[]</includeMutations>
<omitNullInputFields>true</omitNullInputFields>
<maxProjectionDepth>20</maxProjectionDepth>
<outputDir>${project.build.directory}/generated-sources/graphqlcodegen</outputDir>
<kotlinAllFieldsOptional>true</kotlinAllFieldsOptional>
<language>java</language>
</configuration>
</execution>
</executions>
</plugin>
The PageInfo mapping is a circumvention of this issue
The versions of libraries I'm using:
<!-- https://mvnrepository.com/artifact/com.netflix.graphql.dgs.codegen/graphql-dgs-codegen-client-core -->
<dependency>
<groupId>com.netflix.graphql.dgs.codegen</groupId>
<artifactId>graphql-dgs-codegen-client-core</artifactId>
<version>5.1.16</version>
</dependency>
<dependency>
<groupId>com.netflix.graphql.dgs</groupId>
<artifactId>graphql-dgs-client</artifactId>
<version>4.9.20</version>
</dependency>
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by examining the attached schema.txt and reproducing code generation with the GraphQL query and response shown in the issue. Trace the response parsing path for the enum value; done means the generated type can parse this response without failure, with a regression test covering the case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, kotlin
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100