Spring AI中GenAI响应转DTO时如何忽略空ChatResponse字段?
问题解决:Spring AI GenAI响应映射DTO时空对象反序列化失败
核心问题分析
从错误日志可以看出,org.springframework.ai.chat.model.ChatResponse类没有公开的默认构造函数,当GenAI返回的JSON中chatResponse为空对象{}时,Jackson无法实例化该类,导致反序列化失败。同时你希望该字段不存在或为空时不赋值(即设为null)。
解决方案
方案1:自定义ChatResponse替代框架内部类(推荐)
Spring AI的ChatResponse是框架内部类,可能未提供序列化所需的构造器或公开字段,建议自定义一个业务所需的DTO类:
- 创建自定义的
MyChatResponse类,包含你需要的字段并添加默认构造器:
public class MyChatResponse { // 根据业务需求添加字段,例如复制ChatResponse中的messages、metadata等 private List<ChatMessage> messages; private Map<String, Object> metadata; // 必须添加默认构造器,供Jackson反序列化使用 public MyChatResponse() {} // 带参构造器、getter和setter方法 // ... }
- 修改
ChatPromptDTO,将原ChatResponse替换为自定义类:
public class ChatPromptDTO { private String question; private String answer; // 替换为自定义类 private MyChatResponse chatResponse; // getter和setter方法 // ... }
- 可选:添加
@JsonInclude注解,确保空对象不被序列化/反序列化:
import com.fasterxml.jackson.annotation.JsonInclude; public class ChatPromptDTO { private String question; private String answer; @JsonInclude(JsonInclude.Include.NON_EMPTY) private MyChatResponse chatResponse; // getter和setter方法 // ... }
方案2:手动处理JSON响应,替换空对象为null
如果不想自定义类,可以在获取响应后手动修改JSON字符串,将空的chatResponse对象替换为null,再进行反序列化:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.JsonProcessingException; @Override public ChatPromptDTO getResponseAsEntity(String message) { // 获取原始JSON响应 String jsonContent = chatClient.prompt(message).call().content(); // 将空的chatResponse对象替换为null String processedJson = jsonContent.replace("\"chatResponse\": {}", "\"chatResponse\": null"); // 手动反序列化为DTO ObjectMapper objectMapper = new ObjectMapper(); try { return objectMapper.readValue(processedJson, ChatPromptDTO.class); } catch (JsonProcessingException e) { throw new RuntimeException("反序列化响应失败", e); } }
方案3:自定义Jackson反序列化器
通过自定义反序列化逻辑,遇到空对象时直接返回null,避免尝试实例化ChatResponse:
- 创建自定义反序列化器:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import org.springframework.ai.chat.model.ChatResponse; import java.io.IOException; public class ChatResponseDeserializer extends JsonDeserializer<ChatResponse> { @Override public ChatResponse deserialize(JsonParser parser, DeserializationContext context) throws IOException { JsonNode node = parser.getCodec().readTree(parser); // 若节点为空对象,返回null if (node.isEmpty()) { return null; } // 若有有效数据,可尝试反序列化(注意:若ChatResponse无公开构造器,此步骤可能失败) // 此处可根据实际需求调整,比如返回null或抛出异常 return null; } }
- 在DTO字段上添加注解指定反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class ChatPromptDTO { private String question; private String answer; @JsonDeserialize(using = ChatResponseDeserializer.class) private ChatResponse chatResponse; // getter和setter方法 // ... }
内容的提问来源于stack exchange,提问作者Gokul Krishnan J
相关产品推荐
相关产品推荐

