6. 结构化输出让 AI 交作业不是写散文6.1 问题AI 输出的是文本但你要的是对象AI 默认返回的是自然语言文本。但你的程序需要的是结构化的 Java 对象。怎么办// 你想要的是这个recordPerson(Stringname,intage,Stringcity){}// 但 AI 给你的是这个张三今年 25 岁住在北京。他的朋友李四...6.2 BeanOutputConverter文本 → Java Bean// 1. 定义目标类型recordPerson(Stringname,intage,Stringcity){}// 2. 用 ChatClient 的 entity() 方法PersonpersonchatClient.prompt().user(生成一个随机的人物信息).call().entity(Person.class);System.out.println(person.name());// 张三System.out.println(person.age());// 28System.out.println(person.city());// 上海发生了什么Spring AI 在后台做了两件事根据Person类生成 JSON Schema追加到 Prompt 后面作为格式指令拿到 AI 返回的 JSON 后用 Jackson 反序列化成Person对象6.3 泛型类型返回 List// 返回 ListPersonListPersonpeoplechatClient.prompt().user(生成 5 个随机的人物信息).call().entity(newParameterizedTypeReferenceListPerson(){});people.forEach(p-System.out.println(p.name(), p.age()));ParameterizedTypeReference是什么因为 Java 在运行时会擦除泛型类型ListPerson在运行时只是ListSpring AI 需要通过这个匿名内部类的方式拿到实际的泛型参数类型。记住这个写法模板就行每次需要返回泛型集合时照抄。6.4 MapOutputConverter返回 MapMapString,ObjectresultchatClient.prompt().user(u-u.text(列出 {subject} 的 {count} 个属性用 JSON 格式).param(subject,一个 Java 开发者的简历).param(count,5)).call().entity(newParameterizedTypeReferenceMapString,Object(){});System.out.println(result);// {name张三, experience5年, skills[Java, Spring, MySQL, Redis], ...}6.5 ListOutputConverter返回列表ListStringflavorschatClient.prompt().user(u-u.text(列出 {count} 种 {subject}).param(count,10).param(subject,冰淇淋口味)).call().entity(newListOutputConverter(newDefaultConversionService()));flavors.forEach(System.out::println);// 巧克力// 香草// 草莓// ...6.6 Native Structured Output更可靠的结构化一些模型GPT-4o、Claude 3.5 等原生支持结构化输出。Spring AI 用 Advisor 参数来启用PersonpersonchatClient.prompt().advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT).user(生成一个随机的人物信息).call().entity(Person.class);区别普通模式是在 Prompt 里加请输出 JSONAI 可能不听话。Native 模式是把 JSON Schema 传给模型的原生 API模型保证输出符合 Schema。全局启用BeanChatClientchatClient(ChatClient.Builderbuilder){returnbuilder.defaultAdvisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT).build();}6.7 底层用法手动使用 BeanOutputConverter有时候你需要手动控制转换过程BeanOutputConverterPersonconverternewBeanOutputConverter(Person.class);Stringformatconverter.getFormat();// 拿到格式指令StringuserTemplate 生成一个随机人物信息。 {format} ;PromptpromptnewPrompt(PromptTemplate.builder().template(userTemplate).variables(Map.of(format,format)).build().createMessage());GenerationgenerationchatModel.call(prompt).getResult();Personpersonconverter.convert(generation.getOutput().getText());什么时候用底层当你需要自定义 Prompt 模板结构不想用 ChatClient 的自动拼接时。