code

openapi springboot generator jacksonno String-인수 생성자/공장 메서드에서 문자열 값을 역직렬화합니다.

starcafe 2023. 7. 2. 20:51
반응형

openapi springboot generator jacksonno String-인수 생성자/공장 메서드에서 문자열 값을 역직렬화합니다.

사용 중OpenApi SpringBoot생성기를 사용하여 컨트롤러 인터페이스 및 모델을 생성할 수 있습니다.모델 클래스를 만듭니다.JsonNullable<String>null 필드의 경우.하지만 나는 받고 있습니다.Jackson유형 정의 오류 중POST요청이 null 가능 필드에 있는 값으로 전송되었습니다.

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]

에도 같은 일이 일어납니다.Integer또는 다른 유형.요청에 다음 항목만 포함된 경우 작동합니다.non-nullable

여기서 무슨 일이 일어나고 있는지 아십니까?

OpenAPI Generator 팀은 프로젝트에 포함해야 하는 Jackson-data bind-nullable 모듈을 구현했습니다.최신 버전은 0.2.4입니다.

<dependency>
    <groupId>org.openapitools</groupId>
    <artifactId>jackson-databind-nullable</artifactId>
    <version>0.2.4</version>
</dependency>

모듈이 자동으로 감지되지 않는 경우 다음 방법으로 수동으로 감지해야 합니다.

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonNullableModule());

또는 잭슨을 사용하는 경우Spring프로젝트를 등록할 수 있는 방법:

@Bean
@Primary
public Jackson2ObjectMapperBuilder customObjectMapper() {
    return new Jackson2ObjectMapperBuilder()
            // other configs are possible
            .modules(new JsonNullableModule());
}

openapi-generator v5.1.1 이후 config.json에서 다음을 사용할 수 있습니다.

{
  "openApiNullable": false
}

해당 종속성을 제거합니다.생성된 코드를 확인하는 경우 대부분 필요하지 않으므로 클래스 경로에 원하지 않는 종속성을 추가할 수 없습니다.

또는 사용자의 Gradle 플러그인에서 직접build.gradle할 수 있는 일:

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"
    ]
}

@Michaau Ziober가 말했듯이, 당신은 maven 종속성에 jackson-databind-nullable을 추가해야 하며 jackson 모듈을 등록해야 합니다.가장 쉬운 방법은 응용프로그램에 다음을 추가하는 것입니다.

@Configuration
public class JacksonConfig {
  @Bean
  public Module jsonNullableModule() {
    return new JsonNullableModule();
  }
}

Spring은 문서에 나와 있는 대로 ObjectMapper에 Jackson Modules를 자동으로 추가합니다.

com.fasterxml.jackson.databind 유형의 빈입니다.모듈은 자동으로 구성된 Jackson2ObjectMapperBuilder에 자동으로 등록되고 모듈이 생성하는 ObjectMapper 인스턴스에 적용됩니다.이는 응용프로그램에 새 기능을 추가할 때 사용자 지정 모듈을 제공하는 글로벌 메커니즘을 제공합니다.

나를 위한 솔루션(openapi yaml의 자체 생성 코드 외에도):

<dependency>
    <groupId>org.openapitools</groupId>
    <artifactId>jackson-databind-nullable</artifactId>
    <version>0.2.1</version>
</dependency>

그런 다음 @Configuration 클래스/es:

@Bean
public JsonNullableModule jsonNullableModule() {
    return new JsonNullableModule();
}

그리고.

@Bean
public RestTemplate restTemplate(ObjectMapper objectMapper) {
    var converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper);
    return new RestTemplateBuilder().additionalMessageConverters(converter).build();
}

이것은 나에게 효과가 있었고 ObjectMapper에 추가된 포스트 시리얼라이저 모듈을 파괴하지 않는 유일한 솔루션입니다.

@Configuration
public class WebApplicationConfig implements WebMvcConfigurer {
    
    @Bean
    public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
        return new MappingJackson2HttpMessageConverter(objectMapper());
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new StringHttpMessageConverter());
        converters.add(jackson2HttpMessageConverter());
        converters.add(new ByteArrayHttpMessageConverter());
    }

    public ObjectMapper objectMapper() {
        val mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        mapper.registerModule(new JsonNullableModule());
        mapper.registerModule(new JavaTimeModule());
        mapper.registerModule(new Jdk8Module());
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return mapper;
    }

}

언급URL : https://stackoverflow.com/questions/59524404/openapi-springboot-generator-jackson-no-string-argument-constructor-factory-meth

반응형