你有没有遇到过,在前端接收大模型(LLM)数据流时,由于内容还没完全传输完成,
JSON.parse()
解析就直接抛了个错误,把你“吓”得不轻?别慌,今天带你认识一个神奇的小工具——partial-json。它能让咱们在数据还没完全传输完毕时,依旧能“部分地”解析 JSON,看似残缺不全的数据,居然也能“补”起来!本文将结合实际案例,手把手地教你如何把它用到你的前端项目中。
一、背景故事:小李的流式传输“烦恼”
有一位前端开发者小李,最近在用大语言模型(LLM)做一个聊天应用。为了保证聊天过程中回复能“边生成、边显示”,后端就把生成的内容通过流(Stream)的形式一点点返回给前端。这样用户就不用一次性等所有回答都生成完,交互体验相当顺滑。
可问题也来了:
- 后端返回的数据是 JSON,但数据会一点点到达前端;
- 前端此时如果直接用
JSON.parse()
去解析,还没接收完整就会报错。
小李为了解决这个问题,四处找资料,最后发现一个宝藏库——partial-json。它能让不完整的 JSON 数据也能被“补全”解析,简直就是量身定制!
二、什么是 partial-json?
partial-json
是一个支持不完整 JSON 解析的 JavaScript 库。它可以在数据尚未完整的时候,尝试做“最佳推断”,输出当前能得到的可用信息。而且它提供了不同的允许范围(Allow),这让我们可以灵活地控制解析策略,例如允许部分字符串、部分数组、部分对象等等。
可以想象一下,当你从 WebSocket 或者 SSE(Server-Sent Events)中流式接收大模型的输出时,每一帧(chunk)的字符串可能都还没成一个完整的 JSON。partial-json
此时的能力,就是帮你把“半生不熟”的 JSON 智能地“拼出来”一部分,让前端可以先把能呈现的内容先渲染给用户,极大地提升用户体验。
三、使用步骤(以 Vue3 + Vite 为例)
1. 安装依赖
在你的项目根目录执行:
npm install partial-json
2. 集成到前端:代码示例
假设你在 Vue3 项目中使用 Vite 打包。我们在一个简单的组件或工具函数文件里,通过下面几行代码演示如何解析大模型流式返回的数据(或者其它不完整的 JSON 字符串)。
// parsePartialJson.js
import { parse, Allow } from "partial-json";
/**
* @param {string} message - 从后端流式传过来的不完整JSON字符串
*/
export function parseContent(message) {
try {
// 使用 partial-json 的 parse 方法进行解析
let resp = parse(message, Allow.ALL);
// 这里用了 Allow.ALL,让解析过程尽可能地宽松
console.log("解析结果:", resp);
return resp;
} catch (e) {
console.error("Failed to parse message content:", e);
return null;
}
}
代码原理解析
-
import { parse, Allow } from "partial-json"
parse
方法是partial-json
的核心,用于做“不完整 JSON” 的解析。Allow
是一个对象,里面定义了很多允许的“部分解析”类型,例如STR
、OBJ
、ARR
等等,具体后面会详细说明。
-
parse(message, Allow.ALL)
- 这里的第二个参数指定了允许哪些类型的“部分内容”可以被接受。
Allow.ALL
表示 允许最广泛 的部分类型,这样就会尽可能地把已有的内容解析出来。
- 这里的第二个参数指定了允许哪些类型的“部分内容”可以被接受。
-
异常处理
- 尽管
partial-json
能够处理许多“不完整”的情况,但仍不排除遇到严重的语法错误,比如接收到的内容根本不是 JSON 格式。那么就需要在catch
里处理一下,避免页面崩溃。
- 尽管
这样一来,每当有新的一段流式返回的数据到达前端,我们都可以调用 parseContent()
,把它传给解析函数,并将返回的结构在页面上及时展示。
四、深入了解 partial-json 的核心机制
partial-json
底层做了许多字符串解析的工作,它的目标是:
- 当 JSON 字串还没接收完整时,找到一个尽可能合理的截止点,让前端依旧可以获取到当前可用的数据结构。
- 当
Allow
中指定了一些特定类型时,parse
会根据这些类型的允许范围来决定是否继续往下解析,或者在哪个位置**“打住”**。
如果你只想允许部分类型,比如只想允许字符串和对象的部分解析,可以这样:
import { parse, Allow } from "partial-json";
const partialObj = parse('{"message": "Hello', Allow.OBJ);
console.log(partialObj);
// 由于是部分对象,可能会把 "message": "Hello" 解析成一个 key-value,value 还没封闭。
五、高级用法:让你爱不释手
partial-json
提供了一整套可控的 Allow
类型,用来指定不同的“部分容忍”程度。具体见下表:
Allow.STR
: 允许部分字符串Allow.NUM
: 允许部分数字Allow.ARR
: 允许部分数组Allow.OBJ
: 允许部分对象Allow.NULL
: 允许部分 nullAllow.BOOL
: 允许部分布尔值Allow.NAN
: 允许部分 NaNAllow.INFINITY
: 允许部分 InfinityAllow._INFINITY
: 允许部分 -InfinityAllow.INF
: 允许所有正负 InfinityAllow.SPECIAL
: 允许所有特殊值Allow.ATOM
: 允许所有原子值(数字、字符串、布尔、null)Allow.COLLECTION
: 允许数组、对象等集合类型Allow.ALL
: 允许以上所有类型
使用示例
import { parse, Allow } from "partial-json";
const partialJsonString = '{"key": "value"';
// 注意这个字符串少了一个 } ,是典型的不完整 JSON
// 只允许部分对象
let result1 = parse(partialJsonString, Allow.OBJ);
console.log("部分对象:", result1);
// 或者允许所有类型
let result2 = parse(partialJsonString, Allow.ALL);
console.log("所有类型:", result2);
打印结果可能会是:
部分对象: { key: 'value' }
所有类型: { key: 'value' }
因为这段字符串虽然缺了尾部 }
, 但针对部分对象类型,partial-json
已经把它吃下了,并解析出了 key: "value"
!
六、方案价值:前端流式体验的“如虎添翼”
-
降低网络消耗
用流式传输可以让后端分段发送数据,前端也可以分段接收并渲染,用户不用等全部内容到位才看到结果。这种“边加载、边显示”的模式能极大提升使用体验,尤其在大模型场景下显得非常关键。 -
前端快速解析
有了partial-json
,前端再也不怕数据还没来全、JSON 解析报错的问题了。只要有一点点能解析的内容,就能先给用户显示出来,就像“追剧”一样,更新一点看一点。 -
易于集成
partial-json
安装非常简单,使用的 API 也类似于内置的JSON.parse()
,几行代码就能搞定,没有额外的学习成本。 -
灵活度高
通过传入Allow
选项,你可以根据业务场景精细地控制解析级别。- 如果你只想要对象或者数组的部分解析,就不必加载过多类型。
- 如果你想尽可能“通吃”,就直接用
Allow.ALL
就行。
七、总结
对于独立开发者或者前端爱好者来说,大模型应用的火热程度有目共睹。尤其是流式输出,可以让产品的交互体验呈现指数级提升。partial-json
正是为了解决流式 JSON 不完整解析场景而生,让我们不再为临时报错而抓狂,也不用手写一堆“字符串切割”去拼凑 JSON。
如果你正打算在自己的项目里尝试大模型流式传输,不妨把 partial-json
加入到工具箱里。相信等你真正用上这招“边传边渲染”的技术后,会发现前端体验能有多爽快。
“不完整的 JSON 也能继续前行”,这就是它的魅力所在!
题外话:如果你还没“玩”过大模型流式输出,赶紧去试试吧!世界上只有体验过流式才知道它的好。“partial-json” 也只是冰山一角,更多奇技淫巧,还等着你去探索。祝你开发愉快,一起让前端变得更有趣!