spring-ai
spring-ai copied to clipboard
Java 8 date/time type `java.time.Duration` not supported by default
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.time.Duration]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:489)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.writeInternal(AbstractGenericHttpMessageConverter.java:123)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:235)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$HttpMessageConvertingHandler.sendInternal(ResponseBodyEmitterReturnValueHandler.java:221)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$HttpMessageConvertingHandler.send(ResponseBodyEmitterReturnValueHandler.java:212)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.sendInternal(ResponseBodyEmitter.java:223)
... 8 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.Duration not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: org.springframework.ai.chat.model.ChatResponse["metadata"]->org.springframework.ai.chat.metadata.ChatResponseMetadata["rateLimit"]->org.springframework.ai.chat.metadata.EmptyRateLimit["tokensReset"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1330)
at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:183)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:183)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:183)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:502)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:341)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1574)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1061)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:483)
... 13 common frames omitted
Could you please share your related code?
yes,thanks! `@PostMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE) @Operation(summary = "chat") public Flux<ChatResponse> chat() throws InterruptedException { ChatClient.ChatClientRequestSpec chat = chatClient.prompt( new Prompt("hello!!!", options)); Flux<ChatResponse> chatResponseFlux = chat.stream().chatResponse(); return chatResponseFlux; }
` environment:spring ai 1.0.0-M7 springboot 3.3.4
- Which model are you using?
- How did you initialize the
optionsobject?
It worked fine with the Anthropic model.
The name of the model I use is gpt-4o-2024-11-20, which is one of the many models of GPT。
OpenAiChatOptions options = OpenAiChatOptions.builder().model("gpt-4o-2024-11-20").build();
I don't think the problem is that it comes out of the model, but that I return to the Flux<ChatResponse>.I think the reason may be that there is a type Duration in the property of object ChatResponse, which is an error reported by the json handler during serialization, but it cannot be solved by configuring the ObjectMapper.The ObjectMapper code I configured is as follows (it doesn't work):
@Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); return mapper; }
Thank you, seniors!
Thanks seniors, I solved it!
Thanks seniors, I solved it!
@newzhiMing Could you post your solution and close this issue? 😄
The name of the model I use is gpt-4o-2024-11-20, which is one of the many models of GPT。
OpenAiChatOptions options = OpenAiChatOptions.builder().model("gpt-4o-2024-11-20").build();I don't think the problem is that it comes out of the model, but that I return to the Flux.I think the reason may be that there is a type Duration in the property of object ChatResponse, which is an error reported by the json handler during serialization, but it cannot be solved by configuring the ObjectMapper.The ObjectMapper code I configured is as follows (it doesn't work):@Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); return mapper; }Thank you, seniors!
ould you post your solution and close this issue?
OK,This issue arises because of an issue with the JSON serializer that SpringBoot returns to the frontend. Here's how I worked: public static ObjectMapper getJsonObjectMapper() { var objectMapper = new ObjectMapper(); var simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Duration.class, DurationSerializer.INSTANCE); // This is the key code simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); objectMapper.registerModule(simpleModule); return objectMapper; }