首页 / 资讯中心 / 文章详情

JSON工具类设计与AI输出解析:SpringBoot与Uniapp前后端统一实践

JSON工具类设计与AI输出解析:SpringBoot与Uniapp前后端统一实践 ★ FEATURED ARTICLE
“第九讲JSON工具类”这一讲不做推荐算法也不写页面样式而是解决整个项目中一个很容易被忽视、但几乎每个接口都会碰到的底层问题怎么把 Java 对象、AI 返回的大段文本、小程序端接收到的响应数据统一、安全、高效地转换成 JSON。如果你正在做 SpringBoot Vue Uniapp 的分层项目又准备接入 SpringAI 或 LangChain4jJSON 工具类不是那种“随便写一个就能用”的东西。AI 模型返回的文本里经常夹着 Markdown 代码块、空行、前后缀说明后端如果直接用JSON.parse或readValue去解析大概率会抛异常。这一讲会把后端 Java 侧和前端 Uniapp 侧的 JSON 处理一起整理给出可直接落地的工具类、测试方法和接入 AI 推荐接口的完整思路。本文不涉及视频素材的爬取或搬运所有演示都基于正常的推荐接口联调场景涉及用户偏好、观看记录等数据时要注意脱敏和授权不能拿真实用户信息做无边界测试。1. 核心能力速览这一讲要完成的 JSON 工具类不是简单封装一个toJson和parse而是面向项目实际需求的一组能力组合。先看整体规格能力项说明工具定位后端统一 JSON 序列化/反序列化 前端安全解析工具技术底座SpringBoot 项目中使用 Jackson 作为默认 JSON 库前端使用原生 JSON API 做封装后端主要功能对象转 JSON、JSON 转对象、泛型集合转换、JsonNode 动态取值、异常兜底AI 侧功能配合 SpringAI/LangChain4j 的结构化输出把模型返回文本清洗并解析为 DTO前端功能安全解析、空值兜底、对象合并、深拷贝、视频推荐卡片数据格式化批量任务支持批量转换视频元数据、批量读取推荐候选集 JSON 文件、批量解析 AI 输出推荐场景智能视频推荐小程序的接口返回、AI 推荐结果解析、视频卡片列表渲染性能关注点ObjectMapper 单例复用、避免重复序列化、前端长列表分批渲染特殊硬件要求无纯代码层工具AI 模型部分按部署模型环境另行评估这个工具类适合放在整个项目的最底层被 Service、Controller、AI 调用链统一引用。这样后续任何接口返回格式调整只需要改一处。2. 适用场景与使用边界JSON 工具类在这个项目里主要解决四个问题。第一个是接口层的统一返回格式。SpringBoot 后端给 Uniapp 小程序返回数据时通常会包一层统一结果例如code / message / data。如果没有统一工具类每个 Controller 都手动JSON.toJSONString很容易出现字段名不一致、异常时返回空串甚至返回 HTML 错误页的问题。第二个是 AI 模型输出解析。SpringAI 和 LangChain4j 在调用大模型接口时模型返回的本质是一段文本。如果我们在提示词里要求“只返回 JSON”模型大部分时候会遵守但偶尔会加入json代码块标记、前后解释文字或者把布尔值写成字符串。JSON 工具类需要能把这类脏文本清洗后转成 Java 对象。第三个是视频推荐数据的组装。推荐引擎输出候选视频 ID 列表可能是ListLong也可能是ListRecommendItem工具类需要支持泛型反序列化避免每写一个推荐策略就复制一段解析代码。第四个是前端 Uniapp 的数据兜底。Vue 页面拿到接口数据后如果推荐服务异常返回null页面模板里直接访问item.title会报错工具类可以做安全取值。使用边界也要说清楚。这个工具类只负责 JSON 格式转换不负责解决推荐算法准确率问题。它也不是安全边界不要用JSON.parse去解析不可信前端传入的超复杂嵌套字符串不要用工具类绕过接口鉴权。AI 生成的 JSON 如果被直接当协议数据使用必须做字段校验和白名单过滤。3. 环境准备与前置条件这里的开发环境以 SpringBoot 3.x JDK 17 为主前端使用 Vue3 Uniapp 项目。具体版本以你自己项目为准本讲代码使用 Java 17 的语法特性如果还在用 JDK 8需要把部分写法回退为传统写法。后端需准备以下环境JDK 17 或更高版本。Maven 3.8 以上。SpringBoot 3.x 工程已引入 Web 依赖。Jackson 依赖。SpringBoot Web 场景已经自带jackson-databind不需要额外引入。如果已引入 SpringAI 或 LangChain4j确认项目里没有同时存在多个 JSON 库导致序列化冲突。前端 Uniapp 工程需要HBuilderX 或 Vue CLI 创建的 Uniapp 项目。Vue3 组合式 API 写法。不需要额外安装 npm JSON 库使用小程序原生支持的JSON.parse和JSON.stringify即可。磁盘、GPU、内存都没有特殊要求。这个工具类是纯 Java/JavaScript 代码层的内容跟 AI 模型推理资源占用无关只有当 AI 服务本身在本机部署时才需要评估显存和内存。4. 后端 JSON 工具类设计与实现这一讲的核心是写一个JsonUtils工具类。先给完整实现再逐个解释关键点。package com.example.videorecommend.common.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; import java.util.Map; public final class JsonUtils { private static final Logger log LoggerFactory.getLogger(JsonUtils.class); private static final ObjectMapper MAPPER new ObjectMapper(); static { MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); MAPPER.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); } private JsonUtils() { } public static String toJson(Object obj) { if (obj null) { return null; } try { return MAPPER.writeValueAsString(obj); } catch (JsonProcessingException e) { log.error(对象转JSON失败, obj{}, obj, e); return {}; } } public static T T fromJson(String json, ClassT clazz) { if (json null || json.isBlank()) { return null; } try { return MAPPER.readValue(json, clazz); } catch (JsonProcessingException e) { log.error(JSON转对象失败, json{}, json, e); return null; } } public static T T fromJson(String json, TypeReferenceT typeReference) { if (json null || json.isBlank()) { return null; } try { return MAPPER.readValue(json, typeReference); } catch (JsonProcessingException e) { log.error(JSON转泛型对象失败, e); return null; } } public static JsonNode parseNode(String json) { if (json null || json.isBlank()) { return MAPPER.createObjectNode(); } try { return MAPPER.readTree(json); } catch (JsonProcessingException e) { log.error(JSON转JsonNode失败, json{}, json, e); return MAPPER.createObjectNode(); } } public static String getString(JsonNode node, String field) { if (node null || node.get(field) null) { return ; } JsonNode value node.get(field); return value.isTextual() ? value.asText() : value.toString(); } public static ListMapString, Object toMapList(String json) { if (json null || json.isBlank()) { return Collections.emptyList(); } try { return MAPPER.readValue(json, new TypeReferenceListMapString, Object() {}); } catch (JsonProcessingException e) { log.error(JSON转List失败, e); return Collections.emptyList(); } } }这个工具类的设计重点有四个。第一是ObjectMapper 全局单例。SpringBoot 项目中 Web 场景会默认创建自己的 ObjectMapper但如果我们在静态工具类里每次调用都new ObjectMapper()会重复初始化反射缓存和序列化器高并发接口下性能和内存都有损耗。这里把 MAPPER 作为静态常量项目里所有工具类调用都共享这一个实例。第二是反序列化容错。FAIL_ON_UNKNOWN_PROPERTIES设为false表示 JSON 里多出的字段不会导致解析失败。这在 AI 输出场景非常实用大模型经常多输出一个备注字段如果严格校验反而会误伤。ACCEPT_SINGLE_VALUE_AS_ARRAY设为true表示 JSON 里单个对象也能被解析成单元素 List兜底模型输出格式不一致的问题。第三是异常兜底策略。工具类内部捕获所有JsonProcessingException统一记录日志然后返回空对象、空集合或{}。这种设计不是隐藏问题而是让上游业务不会被 JSON 解析异常整个打断。日志里保留原始 JSON 和异常信息方便排查业务层也能通过判断返回值是否为 null 来做降级。第四是泛型支持。TypeReference可以处理ListRecommendItem、MapString, ListLong这类复杂类型而不仅仅是单个 DTO。智能推荐项目里候选集、策略权重、实时特征往往以复杂嵌套结构存在泛型转换是必须的。getString方法解决了 JsonNode 取值的常见问题如果字段不存在直接.asText()会返回字符串null而不是空字符串这里统一处理为空串。实际上项目里还可以增加getLong、getInt、getBoolean等重载按需扩展即可。5. 接入 SpringAI 与 LangChain4j 结构化输出的 JSON 处理工具类写好之后最关键的落地场景就是 AI 返回内容的解析。智能视频推荐小程序中使用 SpringAI 或 LangChain4j 调用大模型时一种常见的做法是让模型输出一个候选视频 ID 列表例如{videoIds: [1001, 1002, 1003], reason: 根据用户最近观看的科技类视频推荐}但实际返回时模型可能给出这样的文本好的这是推荐结果 json {videoIds: [1001, 1002, 1003], reason: 根据用户最近观看的科技类视频推荐}这段文本直接交给 JsonUtils.fromJson 去解析会抛出异常因为前面有 好的这是推荐结果而且外层被 Markdown 代码块包住。这里需要增加一个 AI 文本清洗方法。 java public static String cleanAiJson(String rawText) { if (rawText null) { return ; } String text rawText.trim(); // 去掉可能的 json 代码块标记 int start text.indexOf(); while (start 0) { int end text.indexOf(, start 3); if (end start) { text text.substring(0, start) text.substring(end 3); start text.indexOf(); } else { break; } } int braceStart text.indexOf({); int braceEnd text.lastIndexOf(}); if (braceStart 0 braceEnd braceStart) { return text.substring(braceStart, braceEnd 1); } return text; }这个方法的原理很直接先把 代码块包裹剥掉再截取从第一个{到最后一个}的部分。这样即使模型在 JSON 前后加了说明文字也能提取出真正的 JSON 片段。得到干净的 JSON 字符串之后再调用工具类解析String aiRaw chatClient.prompt() .user(根据用户最近观看记录推荐3个视频ID只返回JSON) .call() .content(); String cleaned JsonUtils.cleanAiJson(aiRaw); RecommendResult result JsonUtils.fromJson(cleaned, RecommendResult.class);如果解析结果为 null说明 AI 输出仍然不合法可以走重试逻辑或返回默认推荐列表。这里需要强调不要盲目相信 AI 输出的字段类型。比如模型把videoIds返回成字符串[1,2,3]解析ListLong时会失败此时可以考虑在提示词里强约束或在解析后用JsonNode手动校准。如果需要通过 SpringAI 的 ChatOptions 让模型以严格 JSON 模式输出不同模型 SDK 的配置方式不一样。以 OpenAI 风格接口为例可以尝试在ChatOptions中添加response_format为json_object但具体参数以你项目实际接入的模型版本为准。比较稳妥的思路是不管模型是否支持 JSON 模式后端都把cleanAiJson作为统一前置处理器双保险。LangChain4j 项目中有些封装也提供了结构化输出能力例如通过AiServices绑定接口来返回对象。但底层仍然要经过 JSON 反序列化JsonUtils中的失败降级仍然有用。建议在接入层写一个统一方法parseAiResult内部完成清洗、解析、校验、日志四个步骤让 Service 层不要直接接触大模型原始文本。6. 前端 Vue/Uniapp 的 JSON 处理工具后端工具类解决 Java 侧的问题Uniapp 小程序端需要另一套轻量工具。小程序页面拿到推荐接口数据后通常会先做格式化再交给列表渲染。先看一个简单但实用的json.js工具模块。这里要特别注意纯数字字段在 JSON 处理中可能被转成字符串的问题。比如videoId: 1001传给小程序端后某些网络库或低版本安卓 WebView 可能将大数字按字符串处理。解决方式后端统一返回字符串 ID前端始终按字符串处理避免精度丢失。这一条在视频推荐接口里尤其重要因为视频 ID 可能超过 JS 安全整数范围。export function safeParse(data, fallback {}) { if (data null || data undefined || data ) { return fallback; } if (typeof data object) { return data; } try { const result JSON.parse(data); return result null || result undefined ? fallback : result; } catch (e) { console.warn(JSON.parse 失败:, data, e); return fallback; } } export function safeStringify(data, fallback {}) { try { return JSON.stringify(data); } catch (e) { console.warn(JSON.stringify 失败:, data, e); return fallback; } } export function getField(obj, path, defaultValue ) { if (!obj || typeof obj ! object) { return defaultValue; } const keys path.split(.); let current obj; for (const key of keys) { if (current[key] null || current[key] undefined) { return defaultValue; } current current[key]; } return current; } export function deepClone(obj) { return safeParse(safeStringify(obj), obj); } export function pickFields(obj, fields []) { if (!obj || typeof obj ! object) { return {}; } const result {}; fields.forEach((field) { if (obj[field] ! undefined) { result[field] obj[field]; } }); return result; }这个工具模块解决的主要问题有四个safeParse避免接口返回空字符串或异常 JSON 时页面崩溃。getField支持user.nickName这种路径读取避免多层判断写成一堆也避免小程序模板中访问不存在字段时报错。deepClone用于推荐卡片组件之间传递对象时隔离引用避免修改一个 item 导致其他卡片联动变化。pickFields用于只提取接口数据中真正需要的字段减少传给日志或本地缓存的数据体积。在 Vue3 页面中使用时可以这样处理推荐接口返回import { safeParse, getField } from /utils/json.js const res await uni.request({ url: /api/recommend/list, method: GET }) const data safeParse(res.data, { code: -1, data: [] }) if (data.code 200) { const recommendList (data.data || []).map((item) ({ videoId: String(getField(item, videoId, )), title: getField(item, title, 未命名视频), cover: getField(item, cover, ), duration: getField(item, duration, 0), reason: getField(item, reason, ) })) this.recommendList recommendList } else { uni.showToast({ title: 推荐服务暂时不可用, icon: none }) }注意这里把videoId强制转成了 String避免后续点击跳转详情页时出现精度问题。这个习惯值得在项目里推广凡是 ID 类字段后端用 String 返回前端用 String 接收统一规范。7. 功能测试与效果验证工具类写到什么程度算合格不能只靠“页面能跑起来”来验证要给出一组可重复的测试规则。后端可以写一个简单的 JUnit 测试类package com.example.videorecommend.common.util; import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; class JsonUtilsTest { Test void testToJsonAndFromJson() { RecommendItem item new RecommendItem(1001L, AI 入门课程, 120); String json JsonUtils.toJson(item); RecommendItem parsed JsonUtils.fromJson(json, RecommendItem.class); assertNotNull(parsed); assertEquals(1001L, parsed.getVideoId()); } Test void testFromJsonWithTypeReference() { String json [{\videoId\:1001,\title\:\A\},{\videoId\:1002,\title\:\B\}]; ListRecommendItem list JsonUtils.fromJson(json, new TypeReferenceListRecommendItem() {}); assertEquals(2, list.size()); } Test void testParseAiOutput() { String raw 好的以下是推荐结果\njson\n{\videoIds\:[1001,1002]}\n; String cleaned JsonUtils.cleanAiJson(raw); assertEquals({\videoIds\:[1001,1002]}, cleaned); } Test void testInvalidJsonReturnFallback() { RecommendItem item JsonUtils.fromJson(not json, RecommendItem.class); assertNull(item); } }判断工具类是否合格的维度测试项输入预期结果失败排查点对象转 JSONRecommendItem对象输出包含videoId、title字段的 JSON检查字段是否有 gettergetter 是否抛出异常JSON 转对象标准 JSON 字符串返回完整 DTO检查 DTO 字段类型与 JSON 字符串是否匹配泛型 List 转换[{videoId:1}]返回ListRecommendItem检查 TypeReference 是否写完整AI 脏文本解析Markdown 包裹 JSON去掉包裹输出完整 JSON 对象检查{和}是否被正确截取非法 JSON 兜底abc返回 null 而不抛异常检查日志中是否记录原始内容前端安全解析null、空串返回默认值页面不报错检查 safeParse fallback 是否生效前端验证方式更直接在 Uniapp 项目的App.vue的onLaunch里临时写一组 mock 数据分别测试空返回值、非法 JSON、正常返回三种情况然后观察页面控制台是否出现Cannot read property之类的报错。建议在开发期使用小程序开发者工具的“模拟接口”能力或者直接在后端写一个测试 Controller返回固定结构的 JSON先把链路打通再接入真实推荐服务。8. 推荐接口 API 与批量任务接入示例JSON 工具类最后要落地到接口。推荐接口通常会返回这样的结构{ code: 200, message: success, data: [ { videoId: 1001, title: SpringBoot 实战, reason: 因为你看过 Java 相关视频 } ] }后端 Controller 返回这个结构时可以直接使用工具类RestController RequestMapping(/api/recommend) public class RecommendController { private final RecommendService recommendService; public RecommendController(RecommendService recommendService) { this.recommendService recommendService; } GetMapping(/list) public String list(RequestParam String userId) { ListRecommendItem items recommendService.recommend(userId); MapString, Object result Map.of( code, 200, message, success, data, items ! null ? items : List.of() ); return JsonUtils.toJson(result); } }这里直接用String作为返回类型配合JsonUtils.toJson输出兼容一些老旧前端网络库。更标准做法是直接返回ResultVO ListRecommendItem 对象由 SpringBoot 自动序列化。两种方式都可以项目统一一种即可。curl 请求示例curl -X GET http://127.0.0.1:8080/api/recommend/list?userIdtest001 \ -H Content-Type: application/json返回结果应当是一个合法的 JSON 字符串。如果接口报错排查顺序依次为Controller 是否注入 Service、Service 是否返回 null、JsonUtils.toJson是否因为循环引用导致{}。批量任务场景更容易体现工具类的价值。智能视频推荐项目可能需要定时处理一批新的视频元数据例如从运营后台导入 CSV再把每条记录转为 JSON 发给推荐服务预热。这时可以写一个批量任务方法public void batchImport(ListVideoMeta videoList) { for (VideoMeta video : videoList) { try { String json JsonUtils.toJson(video); // 发送到推荐引擎或写入消息队列 sendToRecommendEngine(json); Thread.sleep(200); } catch (Exception e) { log.error(批量导入失败, videoId{}, video.getVideoId(), e); // 记录失败任务后续重试 retryQueue.add(video); } } }批量任务的重点不是“转换方法多高级”而是失败隔离和重试。单条数据失败不能影响整个批次JsonUtils.toJson内部虽然不会抛异常但下游发送可能失败需要在业务层捕获。建议给批量任务增加进度日志每处理 100 条打印一次成功/失败数量方便在长时间任务中观察是否卡死。接口调用方还应注意请求超时。AI 推荐链路通常比普通查询慢小程序端请求超时建议设置 10 秒以上。如果 AI 模型推理超过 10 秒前端可以先展示兜底推荐列表再异步刷新 AI 推荐结果避免用户一直等待。9. 性能与稳定性注意事项JSON 处理大多数时候不成为瓶颈但如果项目做起来后接口出现慢请求JSON 工具往往是被忽视的元凶。这里整理几个真实存在的稳定性观察点。第一是 ObjectMapper 实例数量。整个项目尽量只使用一个 ObjectMapper至少每个模块不要重复创建。可以像本讲一样通过静态常量复用也可以直接用 Spring 容器注入的ObjectMapperBean。不要在一个请求里为了转换不同对象而 new 多个实例。第二是大字符串拷贝。cleanAiJson方法里有text.substring操作如果 AI 返回很长substring 会复制原字符串。这个方法只用于 AI 输出清洗一般不会太大问题不大但如果要处理 MB 级 JSON 文件建议改成流式解析例如JsonParser逐个字段读取避免把整个 JSON 一次性加载进内存引起 GC 压力。第三是循环引用检查。实体对象之间如果存在双向关联例如User和WatchRecord互相引用直接用toJson序列化会抛异常即使工具类兜底返回{}也会让调用方莫名拿到空结果。解决办法是在 DTO 层做转换不直接把带关联关系的实体暴露给接口。这比设置JsonIgnore更彻底。第四是前端列表性能。推荐接口返回 50 条视频数据JSON 体量不大但如果每条还包含完整的视频简介、标签、弹幕摘要一次性渲染就会出现白屏。前端拿到推荐列表后优先只渲染首屏 10 条的title / cover / reason再通过onReachBottom加载下一条。第五是日志脱敏。JsonUtils.toJson输出对象后写日志时注意去掉用户敏感字段例如userId、手机号、观看历史里的私密信息。工具类可以增加一个toJsonForLog方法内部先复制对象并置空敏感字段再序列化输出。观察性能可以先从一条推荐接口链路入手用开发者工具的 Network 面板看接口耗时用后端日志看 JSON 序列化耗时占比。如果序列化超过 10ms一般是对象嵌套过深或者writeValueAsString被多次重复调用需要优化结构而不是继续加缓存。10. 常见问题与排查方法问题现象可能原因排查方式解决方案JsonUtils.fromJson返回 nullJSON 字符串格式非法或 DTO 字段类型不匹配查看日志中记录的原始 JSON检查字段名拼写用在线 JSON 校验器检查修正 DTO 类型多字段用FAIL_ON_UNKNOWN_PROPERTIESfalse兜底AI 输出解析失败模型返回的文本包含 Markdown 代码块或说明文字打印cleanAiJson处理前、处理后的结果调用cleanAiJson后再解析若仍失败缩短提示词或改用强制 JSON 模式接口返回{}对象存在循环引用或字段没有 getter检查实体类关联关系检查 Controller 返回的对象使用 DTO 隔离实体不要直接序列化 JPA 关联对象前端data为 undefined后端异常时没有返回 data 字段查看 Network 面板实际响应体后端统一结果类始终包含data字段默认为空数组/空对象大数字 ID 精度丢失后端返回 Long前端 JS 超过安全整数范围在浏览器控制台手动请求接口观察后端 ID 全部改 String前端 String 转换后使用小程序页面白屏模板访问不存在字段或 JSON.parse 异常打开调试器看 console 报错使用safeParse和getField兜底中文乱码后端返回字符串时未指定 UTF-8查看响应头 Content-Type在application.yml设置server.servlet.encoding.forcetrue批量导入任务中途卡住无超时控制或线程阻塞查看 JVM 线程栈给批量任务加线程池、超时和失败重试排查 JSON 相关问题时有一个技巧先把“精确去哪一层”定位清楚。后端用 Postman 直接调用接口看返回的 JSON 是否正常如果后端正常就检查小程序端网络层是否对响应做了二次解析如果小程序端正常就检查页面模板的字段读取路径。只要逐层打印响应体很快能找到出问题的那一层。11. 最佳实践与合规使用JSON 工具类虽小项目规范和边界意识不能丢。列出这一讲建议遵守的最佳实践所有接口返回不乱造结构统一使用Result包装类。即使有些接口只是内部服务调用也保持同样的 JSON 结构方便前端和日志系统统一解析。DTO 字段命名统一采用驼峰式前端小程序中再按需转换为下划线或直接使用驼峰。不要今天用video_id明天用videoId会让工具类形同虚设。List 字段默认给空集合不要给 null。这个决定能省掉前端大量判空代码。AI 解析结果必须校验。不能让 AI 生成的字段直接写入数据库或控制推荐结果至少要做枚举值校验、长度校验、非法字符过滤。涉及用户观看记录、位置、账号信息时必须脱敏和合法授权。JSON 工具类在打日志前要过滤敏感字段真实测试环境不要使用真实用户数据。批量任务中避免无限重试同一批失败数据设置最大重试次数并且记录失败原因到单独的日志文件或表里。代码提交前跑一遍JsonUtilsTest和前端safeParse用例JSON 工具最怕“改了一个公共方法所有接口结构跟着变”回归测试能兜住这类问题。还有一个细节值得强调工具的兜底要适度。JsonUtils.toJson在异常时返回{}这只适合日志和展示场景。如果是交易类、状态类接口异常时返回{}反而掩盖问题宁可让业务层捕获明确错误。所以可以按需扩展一个toJsonStrict方法异常时直接抛出业务异常而不是静默降级。12. 总结与下一步这一讲完成了 JSON 工具类的三个核心部分后端 Jackson 封装、AI 输出清洗、前端 Uniapp 安全解析。最值得优先验证的是cleanAiJson和泛型fromJson因为这两块直接影响后续 AI 推荐结果能不能稳定落库和返回。最容易踩的坑是三个一是ObjectMapper重复创建导致性能隐患二是 AI 输出没有做脏文本清洗就硬解析三是前端直接用JSON.parse去解析可能出现的 null 或异常响应。这三个问题在本讲的工具类里都已经给出对应方案。从整个智能视频推荐小程序项目来看这一讲属于基础设施层。下一讲可以接推荐接口的实际联调或者继续补充 AI 推荐提示词模板、用户特征 JSON 组装、视频去重策略等模块。你可以在当前项目里做三件事把JsonUtils放进公共模块把前端json.js放入utils目录再用 mock 数据跑一遍推荐列表接口确认前后端 JSON 结构完全一致后再进入下一步开发。建议把这一讲收藏备用后面写 AI 模型接入时大概率还要回来调整结构化输出的解析逻辑。
阅读完成 · 觉得有帮助?
咨询建站