diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/metadata/OpenAiChatResponseMetadata.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/metadata/OpenAiChatResponseMetadata.java index 461d090dd..e934e0b50 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/metadata/OpenAiChatResponseMetadata.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/metadata/OpenAiChatResponseMetadata.java @@ -18,6 +18,7 @@ package org.springframework.ai.openai.metadata; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; import org.springframework.ai.chat.metadata.ChatResponseMetadata; import org.springframework.ai.chat.metadata.EmptyRateLimit; import org.springframework.ai.chat.metadata.EmptyUsage; @@ -39,6 +40,7 @@ import java.util.Objects; * @see Usage * @since 0.7.0 */ +@JsonTypeName("openai") public class OpenAiChatResponseMetadata implements ChatResponseMetadata { protected static final String AI_METADATA_STRING = "{ @type: %1$s, id: %2$s, usage: %3$s, rateLimit: %4$s }"; diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatResponseTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatResponseTests.java new file mode 100644 index 000000000..a41d69cda --- /dev/null +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatResponseTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2024 - 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.openai.chat; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.junit.jupiter.api.Test; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.openai.metadata.OpenAiChatResponseMetadata; +import org.springframework.ai.openai.metadata.OpenAiRateLimit; +import org.springframework.ai.openai.metadata.OpenAiUsage; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + +public class OpenAiChatResponseTests { + + @Test + void serDeserChatResponseMetadata() throws JsonProcessingException { + OpenAiUsage openAiUsage = new OpenAiUsage(new OpenAiApi.Usage(1, 2, 3)); + OpenAiRateLimit openAiRateLimit = new OpenAiRateLimit(1L, 2L, Duration.ZERO, 4L, 5L, Duration.ZERO); + OpenAiChatResponseMetadata chatResponseMetadata = new OpenAiChatResponseMetadata("myid", openAiUsage, + openAiRateLimit); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + objectMapper.registerModule(new JavaTimeModule()); + + String json = objectMapper.writeValueAsString(chatResponseMetadata); + System.out.println("ChatResponseMetadata Ser: " + json); + + OpenAiChatResponseMetadata deserialized = objectMapper.readValue(json, OpenAiChatResponseMetadata.class); + assertThat(chatResponseMetadata).usingRecursiveComparison().isEqualTo(deserialized); + } + + @Test + void promptSerialization() throws JsonProcessingException { + Prompt prompt = new Prompt(new UserMessage("hello world")); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + + String json = objectMapper.writeValueAsString(prompt); + System.out.println("Prompt Ser: " + json); + + Prompt deserializedPrompt = objectMapper.readValue(json, Prompt.class); + assertThat(prompt).usingRecursiveComparison().isEqualTo(deserializedPrompt); + } + +} diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java index 936fa0d77..0de4ecc32 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java @@ -71,22 +71,6 @@ class OpenAiChatClientIT extends AbstractIT { record ActorsFilms(String actor, List movies) { } - @Test - void serDeserChatResponseMetadata() throws JsonProcessingException { - OpenAiUsage openAiUsage = new OpenAiUsage(new OpenAiApi.Usage(1, 2, 3)); - OpenAiRateLimit openAiRateLimit = new OpenAiRateLimit(1L, 2L, Duration.ZERO, 4L, 5L, Duration.ZERO); - OpenAiChatResponseMetadata chatResponseMetadata = new OpenAiChatResponseMetadata("myid", openAiUsage, - openAiRateLimit); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - objectMapper.registerModule(new JavaTimeModule()); - String json = objectMapper.writeValueAsString(chatResponseMetadata); - System.out.println("ChatResponseMetadata Ser: " + json); - - OpenAiChatResponseMetadata deserialized = objectMapper.readValue(json, OpenAiChatResponseMetadata.class); - assertThat(chatResponseMetadata).usingRecursiveComparison().isEqualTo(deserialized); - } - @Test void call() throws JsonProcessingException { diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java index 9db9aa720..04f385cc3 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AbstractMessage.java @@ -26,6 +26,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.StreamUtils; @@ -69,8 +71,10 @@ public abstract class AbstractMessage implements Message { this(messageType, textContent, media, Map.of(MESSAGE_TYPE, messageType)); } - protected AbstractMessage(MessageType messageType, String textContent, Collection media, - Map metadata) { + @JsonCreator + protected AbstractMessage(@JsonProperty("messageType") MessageType messageType, + @JsonProperty("content") String textContent, @JsonProperty("media") Collection media, + @JsonProperty("metadata") Map metadata) { Assert.notNull(messageType, "Message type must not be null"); Assert.notNull(textContent, "Content must not be null"); diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java index f8b890416..7897ff9e4 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/AssistantMessage.java @@ -15,6 +15,9 @@ */ package org.springframework.ai.chat.messages; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.Map; /** @@ -25,11 +28,13 @@ import java.util.Map; */ public class AssistantMessage extends AbstractMessage { - public AssistantMessage(String content) { - super(MessageType.ASSISTANT, content); + public AssistantMessage(String textContent) { + super(MessageType.ASSISTANT, textContent); } - public AssistantMessage(String content, Map properties) { + @JsonCreator + public AssistantMessage(@JsonProperty("content") String content, + @JsonProperty("metadata") Map properties) { super(MessageType.ASSISTANT, content, properties); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java index a05ef5226..84b672ec9 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/FunctionMessage.java @@ -15,6 +15,9 @@ */ package org.springframework.ai.chat.messages; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.Map; /** @@ -27,7 +30,9 @@ public class FunctionMessage extends AbstractMessage { super(MessageType.FUNCTION, content); } - public FunctionMessage(String content, Map properties) { + @JsonCreator + public FunctionMessage(@JsonProperty("content") String content, + @JsonProperty("metadata") Map properties) { super(MessageType.FUNCTION, content, properties); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Message.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Message.java index 0945ba8de..bfc0c8710 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Message.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/Message.java @@ -15,6 +15,8 @@ */ package org.springframework.ai.chat.messages; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.springframework.ai.model.Content; /** @@ -25,6 +27,11 @@ import org.springframework.ai.model.Content; * @see Media * @see MessageType */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "messageType") +@JsonSubTypes({ @JsonSubTypes.Type(value = UserMessage.class, name = "USER"), + @JsonSubTypes.Type(value = SystemMessage.class, name = "SYSTEM"), + @JsonSubTypes.Type(value = AssistantMessage.class, name = "ASSISTANT"), + @JsonSubTypes.Type(value = FunctionMessage.class, name = "FUNCTION") }) public interface Message extends Content { MessageType getMessageType(); diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java index 8a9dc5eaa..ac3148dc4 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/SystemMessage.java @@ -15,6 +15,8 @@ */ package org.springframework.ai.chat.messages; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.core.io.Resource; /** @@ -26,7 +28,8 @@ import org.springframework.core.io.Resource; */ public class SystemMessage extends AbstractMessage { - public SystemMessage(String content) { + @JsonCreator + public SystemMessage(@JsonProperty("content") String content) { super(MessageType.SYSTEM, content); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/UserMessage.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/UserMessage.java index 85f071eeb..a0e396827 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/UserMessage.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/messages/UserMessage.java @@ -20,6 +20,8 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.core.io.Resource; /** @@ -45,8 +47,10 @@ public class UserMessage extends AbstractMessage { this(textContent, Arrays.asList(media)); } - public UserMessage(String textContent, Collection mediaList, Map metadata) { - super(MessageType.USER, textContent, mediaList, metadata); + @JsonCreator + public UserMessage(@JsonProperty("content") String content, @JsonProperty("media") Collection mediaList, + @JsonProperty("metadata") Map metadata) { + super(MessageType.USER, content, mediaList, metadata); } @Override diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java index 50848657d..39f3dd229 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatGenerationMetadata.java @@ -15,6 +15,8 @@ */ package org.springframework.ai.chat.metadata; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.springframework.ai.model.ResultMetadata; import org.springframework.lang.Nullable; @@ -25,6 +27,8 @@ import org.springframework.lang.Nullable; * @author John Blum * @since 0.7.0 */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") +@JsonSubTypes({ @JsonSubTypes.Type(value = DefaultChatGenerationMetadata.class, name = "default") }) public interface ChatGenerationMetadata extends ResultMetadata { ChatGenerationMetadata NULL = ChatGenerationMetadata.from(null, null); @@ -39,19 +43,7 @@ public interface ChatGenerationMetadata extends ResultMetadata { * reason} and content filter metadata. */ static ChatGenerationMetadata from(String finishReason, Object contentFilterMetadata) { - return new ChatGenerationMetadata() { - - @Override - @SuppressWarnings("unchecked") - public T getContentFilterMetadata() { - return (T) contentFilterMetadata; - } - - @Override - public String getFinishReason() { - return finishReason; - } - }; + return new DefaultChatGenerationMetadata(finishReason, contentFilterMetadata); } /** diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java index fa62014b0..733e3322a 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/ChatResponseMetadata.java @@ -15,6 +15,7 @@ */ package org.springframework.ai.chat.metadata; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.springframework.ai.model.ResponseMetadata; import java.util.HashMap; @@ -26,6 +27,8 @@ import java.util.HashMap; * @author John Blum * @since 0.7.0 */ + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") public interface ChatResponseMetadata extends ResponseMetadata { static class DefaultChatResponseMetadata extends HashMap implements ChatResponseMetadata { diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/DefaultChatGenerationMetadata.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/DefaultChatGenerationMetadata.java new file mode 100644 index 000000000..ffd228b49 --- /dev/null +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/DefaultChatGenerationMetadata.java @@ -0,0 +1,55 @@ +package org.springframework.ai.chat.metadata; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Objects; + +public class DefaultChatGenerationMetadata implements ChatGenerationMetadata { + + private final String finishReason; + + private final Object contentFilterMetadata; + + @JsonCreator + public DefaultChatGenerationMetadata(@JsonProperty("finishReason") String finishReason, + @JsonProperty("contentFilterMetadata") Object contentFilterMetadata) { + this.finishReason = finishReason; + this.contentFilterMetadata = contentFilterMetadata; + } + + @Override + @JsonProperty("contentFilterMetadata") + public T getContentFilterMetadata() { + return (T) contentFilterMetadata; + } + + @Override + @JsonProperty("finishReason") + public String getFinishReason() { + return finishReason; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof DefaultChatGenerationMetadata)) + return false; + DefaultChatGenerationMetadata that = (DefaultChatGenerationMetadata) o; + return Objects.equals(finishReason, that.finishReason) + && Objects.equals(contentFilterMetadata, that.contentFilterMetadata); + } + + @Override + public int hashCode() { + return Objects.hash(finishReason, contentFilterMetadata); + } + + @Override + public String toString() { + return "DefaultChatGenerationMetadata{" + "finishReason='" + finishReason + '\'' + ", contentFilterMetadata=" + + contentFilterMetadata + '}'; + } + +} diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/model/ChatResponse.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/model/ChatResponse.java index 1c87fc132..954bedb41 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/model/ChatResponse.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/model/ChatResponse.java @@ -15,11 +15,15 @@ */ package org.springframework.ai.chat.model; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.ai.model.ModelResponse; import org.springframework.util.CollectionUtils; import org.springframework.ai.chat.metadata.ChatResponseMetadata; @@ -34,9 +38,9 @@ public class ChatResponse implements ModelResponse { /** * List of generated messages returned by the AI provider. */ - private final List generations; + private List generations = new ArrayList<>(); - private Map advisorContext; + private Map advisorContext = new HashMap<>(); /** * Construct a new {@link ChatResponse} instance without metadata. @@ -58,9 +62,11 @@ public class ChatResponse implements ModelResponse { * @param chatResponseMetadata {@link ChatResponseMetadata} containing information * about the use of the AI provider's API. */ - public ChatResponse(List generations, ChatResponseMetadata chatResponseMetadata, - Map advisorContext) { - this.generations = List.copyOf(generations); + @JsonCreator + public ChatResponse(@JsonProperty("results") List generations, + @JsonProperty("chatResponseMetadata") ChatResponseMetadata chatResponseMetadata, + @JsonProperty("advisorContext") Map advisorContext) { + this.generations = generations; this.chatResponseMetadata = chatResponseMetadata; this.advisorContext = advisorContext; } @@ -81,6 +87,7 @@ public class ChatResponse implements ModelResponse { /** * @return Returns the first {@link Generation} in the generations list. */ + @JsonIgnore public Generation getResult() { if (CollectionUtils.isEmpty(this.generations)) { return null; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/model/Generation.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/model/Generation.java index d9425eb42..925e40bc5 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/model/Generation.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/model/Generation.java @@ -18,6 +18,8 @@ package org.springframework.ai.chat.model; import java.util.Map; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.ai.model.ModelResult; import org.springframework.ai.chat.metadata.ChatGenerationMetadata; import org.springframework.ai.chat.messages.AssistantMessage; @@ -32,6 +34,13 @@ public class Generation implements ModelResult { private ChatGenerationMetadata chatGenerationMetadata; + @JsonCreator + public Generation(@JsonProperty("assistantMessage") AssistantMessage assistantMessage, + @JsonProperty("chatGenerationMetadata") ChatGenerationMetadata chatGenerationMetadata) { + this.assistantMessage = assistantMessage; + this.chatGenerationMetadata = chatGenerationMetadata; + } + public Generation(String text) { this.assistantMessage = new AssistantMessage(text); } @@ -41,11 +50,13 @@ public class Generation implements ModelResult { } @Override + @JsonProperty("assistantMessage") public AssistantMessage getOutput() { return this.assistantMessage; } @Override + @JsonProperty("chatGenerationMetadata") public ChatGenerationMetadata getMetadata() { ChatGenerationMetadata chatGenerationMetadata = this.chatGenerationMetadata; return chatGenerationMetadata != null ? chatGenerationMetadata : ChatGenerationMetadata.NULL; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/Prompt.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/Prompt.java index 1e4b97ed7..4fe12fe73 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/Prompt.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/Prompt.java @@ -20,6 +20,9 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.messages.FunctionMessage; import org.springframework.ai.chat.messages.Message; @@ -54,11 +57,14 @@ public class Prompt implements ModelRequest> { this(Collections.singletonList(message), modelOptions); } - public Prompt(List messages, ChatOptions modelOptions) { + @JsonCreator + public Prompt(@JsonProperty("instructions") List messages, + @JsonProperty("options") ChatOptions modelOptions) { this.messages = messages; this.modelOptions = modelOptions; } + @JsonIgnore public String getContents() { StringBuilder sb = new StringBuilder(); for (Message message : getInstructions()) { diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/Content.java b/spring-ai-core/src/main/java/org/springframework/ai/model/Content.java index ea1eb741a..cb37d04a3 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/Content.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/Content.java @@ -1,5 +1,6 @@ package org.springframework.ai.model; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.springframework.ai.chat.messages.Media; import java.util.Collection; @@ -15,6 +16,7 @@ import java.util.Map; * @author Christian Tzolov * @since 1.0.0 */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") public interface Content { /** diff --git a/spring-ai-core/src/test/java/org/springframework/ai/chat/client/AdvisedRequestTests.java b/spring-ai-core/src/test/java/org/springframework/ai/chat/client/AdvisedRequestTests.java new file mode 100644 index 000000000..0732d8309 --- /dev/null +++ b/spring-ai-core/src/test/java/org/springframework/ai/chat/client/AdvisedRequestTests.java @@ -0,0 +1,32 @@ +package org.springframework.ai.chat.client; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class AdvisedRequestTests { + + @Test + void serDeserAdvisedRequest() throws JsonProcessingException { + + AdvisedRequest.Builder builder = AdvisedRequest.builder(); + AdvisedRequest advisedRequest = builder.withSystemText("This is system text") + .withUserText("This is user text") + .build(); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + objectMapper.registerModule(new JavaTimeModule()); + + String json = objectMapper.writeValueAsString(advisedRequest); + System.out.println("AdvisedRequest Ser: " + json); + + AdvisedRequest deserialized = objectMapper.readValue(json, AdvisedRequest.class); + assertThat(advisedRequest).usingRecursiveComparison().isEqualTo(deserialized); + } + +}