当前位置: 首页 > 知识库问答 >
问题:

无法从openapi客户端中的String反序列化java.time.OffsetDateTime类型的值

柴泰平
2023-03-14

我有一个spring boot应用程序,通过gradle插件生成一个java客户端:

openApiGenerate {
    generatorName = "java"
    inputSpec = specsYml
    outputDir = "$buildDir/generated".toString()
    apiPackage = "com.customapi.api"
    invokerPackage = "com.customapi.invoker"
    modelPackage = "com.customapi.model"
    configOptions = [
        dateLibrary: "java8",
        library    : "resttemplate"
    ]
}

我选择了“java8”作为dateLibrary,因为这似乎是使用java1.8的项目的首选。

对于生成的客户端,我正在执行一个请求,该请求返回一个包含时间戳的对象。我得到以下错误:

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    ...
Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class com.customapi.model.Info] and content type [application/json];
    ...
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.OffsetDateTime` from String "2020-07-21T12:12:23.000+0200": ...
   ...
...
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.OffsetDateTime` from String "2020-07-21T12:12:23.000+0200": Failed to deserialize java.time.OffsetDateTime: (java.time.format.DateTimeParseException) Text '2020-07-21T12:12:23.000+0200' could not be parsed at index 23
 at [Source: (ByteArrayInputStream); line: 1, column: 84] (through reference chain: com.customapi.model.Info["buildTimestamp"])
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1679) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:935) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:86) ~[jackson-datatype-jsr310-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:218) ~[jackson-datatype-jsr310-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:50) ~[jackson-datatype-jsr310-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218) ~[jackson-databind-2.10.3.jar:2.10.3]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3267) ~[jackson-databind-2.10.3.jar:2.10.3]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:269) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    ... 17 common frames omitted
Caused by: java.time.format.DateTimeParseException: Text '2020-07-21T12:12:23.000+0200' could not be parsed at index 23
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) ~[na:1.8.0_151]
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777) ~[na:1.8.0_151]
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:212) ~[jackson-datatype-jsr310-2.10.3.jar:2.10.3]
    ... 24 common frames omitted

有关Info类的相关部分:

...
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", date = "2020-07-26T14:09:54.137+02:00[Europe/Berlin]")
public class Info {
    ...
    public static final String JASON_PROPERTY_BUILD_TIMESTAMP = "buildTimestamp";
    private OffsetDateTime buildTimestamp;
    ...
    public Info buildTimestamp(OffsetDateTime buildTimestamp) {
        this.buildTimestamp = buildTimestamp;
        return this;
    }

    public void setBuildTimestamp(OffsetDateTime buildTimestamp) {
        this.buildTimestamp = buildTimestamp;
    }
    ...
}

这两种setter方法都接受OffsetDateTime对象,并且没有注释,因此转换必须在别处进行。输入字符串也是“2020-07-21T12:12:23.000 0200”。相关依赖项包括

ext {
    swagger_annotations_version = "1.5.22"
    jackson_version = "2.10.3"
    jackson_databind_version = "2.10.3"
    jackson_databind_nullable_version = "0.2.1"
}

dependencies {
    compile "io.swagger:swagger-annotations:$swagger_annotations_version"
    compile "com.fasterxml.jackson.core:jackson-core:$jackson_version"
    compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
    compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
    compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version"
    compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version"
    compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
}

jackson和Java8似乎有很多问题,这个站点上的大多数解决方案似乎都在添加注释。但我怀疑修改生成的代码是正确的解决方案。生成客户机时是否忽略了一个重要参数?服务器是否提供了错误的格式?我该如何调查这件事?

当我切换dateGallery遗留它的工作原理,所以我认为我收到正确的数据。

(jaxrs)服务器生成器中存在错误https://github.com/swagger-api/swagger-codegen/issues/3648#issuecomment-244056314,服务器发送的数据格式错误(不带冒号)日期时间。我的解决方案是为客户端使用遗留dateLibrary,它可以处理错误的格式。

共有2个答案

阳德润
2023-03-14

我通过切换dateGalleryjava8-localdatetime得到了帮助

另见此处。

子车睿
2023-03-14

根据我在问题中的评论,我意识到您不需要Jackson注释。你只需要调整一下设定器。下面是一个基本演示:

假设以下类别:

import java.time.OffsetDateTime;
//import com.fasterxml.jackson.annotation.JsonSetter;
import java.time.format.DateTimeFormatter;

public class MyOdt {
    
    private OffsetDateTime odt;

    public OffsetDateTime getOdt() {
        return odt;
    }

    //@JsonSetter("odt")
    public void setOdt(String odtString) {
        final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSxx";
        DateTimeFormatter dtfB = DateTimeFormatter.ofPattern(pattern);
        this.odt = OffsetDateTime.parse(odtString, dtfB);
    }
    
}

该类将从JSON片段创建,如下所示:

String jsonTest = "{ \"odt\" : \"2020-07-21T12:12:23.000+0200\" }";

对象映射器:

ObjectMapper objectMapper = new ObjectMapper()
        .registerModule(new JavaTimeModule())
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

MyOdt odtTest = objectMapper.readValue(jsonTest, MyOdt.class);

以下是问题的原始意见供参考:

观察:这不是要由OffsetDateTime解析的有效字符串。parse()因为默认的日期时间格式要求偏移量中有冒号:02:00。所以,这是有效的:OffsetDateTime。解析(“2020-07-21T12:12:23.000 02:00”)

 类似资料:
  • 我有一门课是这样的: 但是当我试图序列化它时,我收到一个错误,上面写着“试图序列化java.lang.class:java.lang.字符串。忘记注册一个类型适配器了吗?”。所以我创建了这个适配器: } 并登记如下: 但我还是犯了同样的错误<我做错了什么 适配器的实现看起来正常吗?

  • 使用Spring1.5.8释放Jackson mapper,给出以下异常。 在[源:未知;行:-1,列:-1](通过引用链:com.copart.conversationapi.CallDisposition.model.vo.CallLogEntity[“CallEndTime”]) Callentity.java java pom.xml

  • 由于以下异常,我无法反序列化Java-8-locatedate JSON分析错误:无法从字符串“15/09/1978”反序列化< code>java.time.LocalDate类型的值:无法反序列化Java . time . local date(Java . time . format。无法在索引0处分析DateTimeParseException)文本“15/09/1978”; 包含Date

  • 我试图在电影和用户之间建立多对多的关系。当我保存电影时,我会收到这个错误: 2017-12-01 16:12:43.351警告17328---[nio-8090-exec-5]。c、 j.MappingJackson2HttpMessageConverter:未能评估类型[[simple type,class com.movieseat.models.Movie]]:java的Jackson反序列

  • 如果我发送下面的正文,Post API在postman或swagger上工作正常。 但是MockMVC测试用例在Spring Boot项目中给出了以下错误 错误请求:JSON解析错误:意外字符('C'(代码67)):期望逗号分隔Object条目;嵌套异常com.fasterxml.jackson.core.JsonParseException:意外字符('C'(代码67)):期望逗号分隔Objec

  • 问题内容: 我有一个具有两列的DataTable。ShipmentDate(DateTime)和Count(Int)。在对字符串反序列化之后,我发现如果第一个itemarray值为null,则ShipmentDate的类型将变为字符串。 检查以下示例。除了第一个数组项,两个json字符串都具有相同的数据。 在我的场景中,第一个项目数组的ShipmentDate可以为null,并且将其转换为字符串类