目录结构化输出AI 结果映射为 POJO《Spring AI 实战系列》完整目录 入门篇已完结 · 建议按顺序学习 进阶篇更新中️ 学习路径建议一、为什么需要结构化输出1.1 AI 返回的是字符串1.2 手动解析的痛苦1.3 结构化输出的价值二、Spring AI 的解决方案2.1 两种方案2.2 BeanOutputConverter 原理三、BeanOutputConverter 用法3.1 基础用法3.2 带格式控制的转换器3.3 常用 POJO 示例四、Native Structured Output4.1 什么是 Native4.2 启用原生结构化输出五、泛型集合处理5.1 返回 ListT5.2 返回 MapString, T5.3 流式响应 结构化输出六、实战案例6.1 案例智能数据分析助手6.2 案例表单数据提取七、系列预告本篇小结系列回顾 参考资料 收藏关注持续更新结构化输出AI 结果映射为 POJO系列说明本文为《Spring AI 实战系列 入门篇》第 4 篇前置知识完成第 1-3 篇预计阅读时间12 分钟《Spring AI 实战系列》完整目录 学习不迷路系列持续更新中点击链接直达各篇 入门篇已完结 · 建议按顺序学习篇目标题核心内容第 1 篇✅核心概念与快速上手Model / Prompt / Embedding 第一个项目第 2 篇✅Tool Calling让 AI 调用外部函数Tool声明式 编程式工具定义第 3 篇✅VectorStore RAG构建私有知识库向量数据库集成 文档检索第 4 篇✅结构化输出AI 结果映射为 POJOBeanOutputConverter第 5 篇✅Advisors自定义 AI 中间件拦截器链 对话记忆第 6 篇✅国产模型集成指南通义千问 / 文心一言 / 智谱 GLM 进阶篇更新中篇目标题核心内容进 1✅智能客服系统多轮对话 工具调用 人工兜底进 2✅企业知识库 RAG 管线多格式 ETL 混合检索RRF进 3AI Agent 自主规划ReAct 模式 多工具编排️ 学习路径建议Week 1-3 【入门篇】第1篇 → 第2篇 → 第3篇 → 第4篇 → 第5篇 → 第6篇 └→ 掌握 Spring AI 核心能力 Week 4-6 【进阶篇】智能客服 → 企业RAG → AI Agent └→ 实战企业级 AI 应用一、为什么需要结构化输出1.1 AI 返回的是字符串❌ 问题AI 返回的是字符串不是数据结构 用户生成一个用户信息 AI{name: 张三, age: 25, email: zhangsanexample.com} 这看起来像 JSON但 AI 返回的是 String json {\name\: \张三\, ...}; // 只是一段字符串1.2 手动解析的痛苦// ❌ 传统方式字符串解析StringresponsechatClient.prompt().user(生成用户信息).call().content();// 返回的是字符串// 手动解析 JSONObjectMappermappernewObjectMapper();Userusermapper.readValue(response,User.class);// 可能失败1.3 结构化输出的价值✅ 目标直接获得 Java 对象 User user chatClient.prompt() .user(生成用户信息) .call() .entity(User.class); // 直接返回 User 对象二、Spring AI 的解决方案2.1 两种方案方案说明适用场景BeanOutputConverterSpring AI 自动转换通用方案Native Structured Output模型原生支持OpenAI 等2.2 BeanOutputConverter 原理┌─────────────────────────────────────────┐ │ BeanOutputConverter 转换流程 │ ├─────────────────────────────────────────┤ │ │ │ 1. 获取 Java 类定义 │ │ User { name, age, email } │ │ ↓ │ │ 2. 生成 JSON Schema │ │ {type: object, properties:...} │ │ ↓ │ │ 3. 构建 Prompt含 Schema │ │ 请返回 JSON格式如下... │ │ ↓ │ │ 4. AI 返回字符串 │ │ {name: 张三...} │ │ ↓ │ │ 5. 解析为 Java 对象 │ │ User(name张三, age25, ...) │ │ │ └─────────────────────────────────────────┘三、BeanOutputConverter 用法3.1 基础用法定义 POJOpublicrecordUser(Stringname,intage,Stringemail){}使用 .entity()RestControllerpublicclassOutputController{privatefinalChatClientchatClient;publicOutputController(ChatClient.Builderbuilder){this.chatClientbuilder.build();}GetMapping(/user)publicUsergenerateUser(){returnchatClient.prompt().user(生成一个用户信息包含姓名、年龄、邮箱).call().entity(User.class);}}3.2 带格式控制的转换器GetMapping(/recipe)publicRecipegetRecipe(){// 创建转换器BeanOutputConverterRecipeconverternewBeanOutputConverter(Recipe.class);// 获取期望的格式字符串Stringformatconverter.getFormat();// 调用 AI传入格式要求ReciperecipechatClient.prompt().user(u-u.text(请生成一个菜谱格式如下\n{format}).param(format,format)).call().entity(converter);returnrecipe;}3.3 常用 POJO 示例// 菜谱publicrecordRecipe(Stringname,ListStringingredients,ListStringsteps,intcookingTime,Stringdifficulty){}// 电影信息publicrecordMovie(Stringtitle,Stringdirector,intyear,doublerating,ListStringgenres){}// 产品信息publicrecordProduct(Stringname,Stringdescription,doubleprice,Stringcurrency,ListStringtags){}四、Native Structured Output4.1 什么是 Native部分 AI 模型如 OpenAI GPT-4、Anthropic Claude原生支持结构化输出直接返回 JSON。// ✅ 使用原生结构化输出ActorFilmsfilmschatClient.prompt().advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)// 启用原生.user(生成一个演员和其代表作品).call().entity(ActorFilms.class);4.2 启用原生结构化输出// 方式1全局启用ChatClientchatClientChatClient.builder(chatModel).defaultAdvisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT).build();// 方式2单次调用启用chatClient.prompt().advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT).user(生成数据).call().entity(MyClass.class);五、泛型集合处理5.1 返回 List// 定义类型ParameterizedTypeReferenceListUsertypeRefnewParameterizedTypeReference(){};// 调用ListUseruserschatClient.prompt().user(生成5个用户信息).call().entity(typeRef);5.2 返回 MapString, TParameterizedTypeReferenceMapString,IntegertypeRefnewParameterizedTypeReference(){};MapString,IntegerscoreschatClient.prompt().user(统计每个科目的分数数学95语文88英语92).call().entity(typeRef);5.3 流式响应 结构化输出// 需要先收集流再转换BeanOutputConverterListMovieconverternewBeanOutputConverter(newParameterizedTypeReference(){});FluxStringfluxchatClient.prompt().user(推荐5部科幻电影).stream().content();Stringcontentflux.collectList().block().stream().collect(Collectors.joining());ListMoviemoviesconverter.convert(content);六、实战案例6.1 案例智能数据分析助手publicrecordSalesReport(Stringregion,doubletotalRevenue,intorderCount,doubleaverageOrderValue,ListProductPerformancetopProducts){}publicrecordProductPerformance(StringproductName,intquantity,doublerevenue){}RestControllerRequestMapping(/analytics)publicclassAnalyticsController{privatefinalChatClientchatClient;publicAnalyticsController(ChatClient.Builderbuilder){this.chatClientbuilder.build();}GetMapping(/report)publicSalesReportgetReport(RequestParamStringregion,RequestParamStringperiod){BeanOutputConverterSalesReportconverternewBeanOutputConverter(SalesReport.class);Stringprompt 分析以下销售数据返回 JSON 格式 地区%s 时间段%s 返回格式 %s 注意 - totalRevenue 是总销售额 - orderCount 是订单数量 - averageOrderValue 是平均订单金额 - topProducts 是前3个畅销产品 .formatted(region,period,converter.getFormat());returnchatClient.prompt().user(prompt).call().entity(converter);}}6.2 案例表单数据提取publicrecordExtractedFormData(StringfullName,Stringemail,Stringphone,Stringaddress,StringdateOfBirth){}ServicepublicclassFormExtractionService{privatefinalChatClientchatClient;publicFormExtractionService(ChatClient.Builderbuilder){this.chatClientbuilder.build();}/** * 从文本中提取表单数据 */publicExtractedFormDataextractFromText(Stringtext){BeanOutputConverterExtractedFormDataconverternewBeanOutputConverter(ExtractedFormData.class);returnchatClient.prompt().user(u-u.text(从以下文本中提取表单信息\n\n{text}\n\n返回 JSON\n{format}).param(text,text).param(format,converter.getFormat())).call().entity(converter);}}七、系列预告本篇小结✅ 理解了为什么需要结构化输出✅ 掌握了 BeanOutputConverter 用法✅ 学会了泛型集合处理系列回顾好消息入门篇全部 6 篇已完结进阶篇持续更新中 入门篇完结 —— 恭喜你已完成第 4 篇推荐学习路径第1篇 → 第2篇 → 第3篇 → 第4篇本文✅→ 第5篇Advisors 参考资料Spring AI Structured Output 文档https://docs.spring.io/spring-ai/reference/api/structured-output-converter.htmlBeanOutputConverter APIorg.springframework.ai.support. BeanOutputConverter引用说明本文核心概念与技术描述参考自 Spring AI 官方文档https://docs.spring.io/spring-ai/reference/结构化输出内容来自官方 Structured Output Converter 章节。 收藏关注持续更新如果觉得有帮助请⭐收藏本文—— 方便后续查阅随时回顾核心概念关注公众号「AI日撰」—— 点击菜单「获取源码」获取完整代码Gitee 仓库分享给同事—— 一起学习 Spring AI少走弯路系列更新不迷路下篇推荐第 5 篇 · Advisors自定义 AI 中间件