I'm using OpenApi
SpringBoot
generator to generate controller interfaces and models. This creates model classes with JsonNullable<String>
for nullable fields. However I'm getting a Jackson
type definition error while POST
request is sent with value present in a nullable field.
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.openapitools.jackson.nullable.JsonNullable` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('TG')
at [Source: (PushbackInputStream); line: 3, column: 19] (through reference chain: com.example.rest.CreateRequest["displayName"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013) ~[jackson-databind-2.9.7.jar:2.9.7]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084) ~[jackson-databind-2.9.7.jar:2.9.7]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:204) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:157) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
Same thing happens for Integer
or any other type. It works if the request contains only non-nullable
fields.
Any idea what is going wrong here ?
Since openapi-generator v5.1.1 you can use in your config.json:
{
"openApiNullable": false
}
To remove that dependency. Most of the time it's not needed (if you check the generated code), so it's cool to be able to not add an unwanted dependency in your class path.
Or directly in the gradle plugin in your build.gradle
you can do:
openApiGenerate {
generatorName = "spring"
inputSpec = "$rootDir/specs/petstore-v3.0.yaml"
outputDir = "$buildDir/generated"
apiPackage = "org.openapi.example.api"
modelPackage = "org.openapi.example.model"
configOptions = [
openApiNullable: "false"
]
}
OpenAPI Generator team implemented jackson-databind-nullable module which you should include to your project. The newest version is 0.2.3.
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.3</version>
</dependency>
If module will not be detected automatically you need to do it manually by:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonNullableModule());
Or if you using Jackson in Spring
project, then you can register it by:
@Bean
@Primary
public Jackson2ObjectMapperBuilder customObjectMapper() {
return new Jackson2ObjectMapperBuilder()
// other configs are possible
.modules(new JsonNullableModule());
}
As @Michał Ziober said, you have to add jackson-databind-nullable to your maven dependencies and need to register the jackson module. The easiest way though is to add the following to your application:
@Configuration
public class JacksonConfig {
@Bean
public Module jsonNullableModule() {
return new JsonNullableModule();
}
}
Spring automatically adds Jackson Modules to the ObjectMapper, as the docs say:
Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates. This provides a global mechanism for contributing custom modules when you add new features to your application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With