响应 A
响应 B

API 响应 Diff:在线比较 JSON API 数据

将预期的响应粘贴到左侧,实际收到的响应粘贴到右侧,即可查看每个发生变化的字段。专为后端、QA 和集成工作设计。不离开您的浏览器。

这个 API 响应 diff 工具是什么

一个免费的浏览器内工具,用于比较两个 HTTP API 响应体。将从 staging 获取的 JSON 粘贴到左侧,从 production 获取的 JSON 粘贴到右侧,差异会逐字符高亮显示。文本不会离开您的设备,这一点很重要,因为真实的 API 响应经常包含用户邮件地址、会话令牌、内部用户 ID 等不应上传到第三方 diff 网站的敏感信息。

它专为以下场景而设计:某个集成测试在 CI 中偶发性失败,您有本地 Postman 运行时正常响应的截图,以及 CI 构建器日志中失败响应的记录。为了一次性调试而搭建完整的 Pact 契约测试 过于繁重。两个文本面板,一次 diff,通常不到一分钟就能将问题缩小到单个字段。

底层 diff 引擎与我们的 compare-json 工具 相同,只是针对 API 测试工作流进行了定制。如果您的响应是 XML 或 SOAP 信封,请使用我们的 compare-xml 页面。如果需要对 webhook 日志或审计记录等自由文本进行 diff,则使用 compare-text 工具

API 响应 diff 的实际作用

API 响应 diff 填补了两种相关但不同测试方法之间的空白。OpenAPI 3.1 的 schema diff 告诉您契约什么发生了变化:新增了可选字段、属性被重命名、enum 变得更严格。快照测试(Jest 快照、Vitest 快照、pytest-snapshot)告诉您代码产生的输出相对于保存的 fixture 有何变化。本工具处于运行时层面。您提供两个真实响应体,它显示每个不同的字节,无论 schema 是否允许该变更,也无论快照 fixture 是否是最新的。

这有什么用?因为在 REST 集成工作中最棘手的 bug 往往不是 schema 违规,而是微妙的漂移:序列化器在 Jackson 升级后悄悄将日期从 ISO-8601 换成了 Unix 时间戳;Marshmallow schema 开始发送 null 而不是省略缺失字段;DRF ViewSet 在某次中间件变更后开始将响应包装在 data 信封中。OpenAPI spec 没有变化,快照没有更新,测试单独通过,集成却断了。响应体 diff 能捕获所有这些,因为它不关心契约,只关心字节。

易变字段是最需要注意的。时间戳、请求 ID、trace ID、服务器生成的 UUID 和分页游标,在同一接口的任意两次捕获之间都会不同,即使没有实质性变化。正确的做法是在 diff 之前先规范化:用占位符替换时间戳,删除 trace ID,在顺序不具有契约意义的情况下对数组排序。Pact 等工具通过匹配器来处理这些问题;在本工具中,您通过编辑面板来处理,十秒钟即可消除噪音。

三步完成 API 响应 diff

两个文本面板,一次 diff。无需登录,无需上传,无需配置代理。

  1. 1

    捕获第一个响应

    使用 curl、httpie、Postman、Insomnia 或团队常用工具调用接口。curl -s https://api.example.com/v1/users/123 | jq 是不错的基准,因为 jq 会格式化 JSON,使 diff 更易阅读。复制响应体(只要 JSON,不要 header),粘贴到左侧面板。如果从 CI 日志中提取,请先去掉大多数日志工具添加的时间戳前缀,确保 diff 落在实际的响应数据上。

  2. 2

    捕获第二个响应

    调用比较源:另一个环境、另一个 API 版本或另一个服务商。使用相同的捕获方式和格式化步骤,粘贴到右侧面板。如果一个捕获来自录制的 fixture(vcrpy、pollyjs、MSW、nock),另一个是实时数据,请先规范化明显的易变字段:清除 request_id,用常量替换时间戳,删除泄漏到响应体中的 trace header。剩余的 diff 才是真正有意义的信号。

  3. 3

    阅读高亮的差异

    左侧以红色删除线显示删除内容,右侧以绿色显示插入内容。每个面板头部的变更计数器显示 diff 找到的独立编辑数量。优先关注三件事:状态字符串的变化、缺失或新增的键、值类型的变化(字符串变为数字、对象变为 null)。这三类几乎涵盖了所有真实的 API 回归。格式和顺序的变化通常是噪音,除非您的消费者依赖它们。

适合使用 API 响应 diff 的场景

复现偶发性集成测试失败

测试在本地通过,在 CI 中失败。您有本地 Postman 运行时捕获的响应,以及 CI 构建代理捕获的响应(大多数 CI 系统可以用 verbose 参数输出请求/响应)。将两者粘贴到 diff 工具中。十有八九,差异是环境因素:不同的功能标志、过时的 fixture、构建运行器上的时区偏移。剩下的那一次是真正的 bug,而您已经将问题定位到了某个具体字段。

对照最新响应验证 fixture

您的仓库中有一个模拟第三方 API 的 fixture 文件,用于测试。上游服务商刚发布了新的 minor 版本。用 curl 调用线上接口,将响应粘贴到 fixture 旁边,就能清楚地看到哪些字段发生了漂移。这是 VCR 风格回放工具 自动化工作的手动版本。当您只想更新一个 fixture 而不想重新录制整个测试套件时很有用。

验证 API 版本向后兼容性

您即将发布内部 API 的 v2,但 v1 客户端仍在生产环境运行。分别调用 /v1/orders/42/v2/orders/42 并对比响应。任何被删除的字段、被重命名的键、值类型的变化对 v1 客户端来说都是破坏性变更;任何新增字段是向后兼容的。这是一种简单版的消费者驱动契约测试,不适合大规模接口检查,但对于一两个接口的快速验证很有效。

发现序列化器回归

团队升级了 Jackson、Marshmallow、DRF 或类似的序列化层,测试通过了。然后下游消费者报告解析出错。在旧分支和新分支上分别捕获同一接口的响应并进行 diff。常见发现:日期格式从 2026-05-09T10:00:00Z 变成了 Unix 时间戳,小数丢失了尾随零,enum 开始序列化为整数而不是字符串,或以前被省略的 null 字段开始出现在响应体中。

比较两个服务商或版本的 webhook 数据

Stripe webhook 同一事件类型的 V1 和 V2 看起来几乎一样,实际上相差甚远。GitHub webhook 事件数据在不同 API 版本之间,以及 Slack 事件订阅在不同 scope 之间,也是如此。将每个服务商的示例数据粘贴到 diff 工具中,即可看到被重命名的字段、移动的嵌套对象和新增的元数据块。这比并排阅读两份服务商文档更快,尤其是当文档对实际出现的字段一笔带过时。

调试"在 staging 正常,在 production 出错"

经典的部署难题:相同的客户端请求从 staging 和 production 返回了微妙不同的 JSON。捕获两者,粘贴比较,差异通常是配置标志、缺失的功能开关或过时的缓存响应。这同样适用于多区域调试(us-east-1 与 eu-west-1 返回不同数据)、CDN 缓存问题(缓存了过时的响应体)以及读副本延迟(写操作尚未同步到所有副本)。

值得了解的 API 响应 diff 边缘情况

响应体 diff 与您的测试框架、OpenAPI 工具或肉眼判断不一致的情况。在假设 diff 发现了真正 bug 之前,值得快速浏览一遍。

TopicWhat this tool does
易变字段(时间戳、ID)created_atupdated_atrequest_idtrace_id、服务器生成的 UUID 和分页游标,在任意两次捕获之间都会不同。用 jq 'del(...)' 规范化,用常量替换,或在 diff 之前直接编辑掉。您真正关心的信号在别处。
null 与缺失键{"foo": null}{} 在 JSON 中是不同的,许多序列化器(Marshmallow、Jackson、System.Text.Json)都有开关来切换这两种行为。diff 会捕获这种差异。某些客户端将它们视为等价,其他客户端不会;正确答案取决于您的消费者如何处理,这也是序列化器升级后常见的回归来源。
键顺序RFC 8259 定义 JSON 对象为无序。两个语义相同但键顺序不同的响应在这里会显示为 diff,因为文本比较是顺序敏感的。如果需要顺序无关的 diff,先用 jq --sort-keys 对两侧进行排序。注意那些实际依赖顺序的少数消费者(某些签名流程、某些遗留解析器)。
数组顺序JSON 数组是有序的,但许多 API 返回的数组顺序在契约上并不重要:权限列表、功能标志列表、webhook 订阅列表。即使消费者不在意,diff 也会将重新排序的数组标记为变更。如果重排序在您的领域无害,请先按稳定键对两侧排序再进行 diff。
JSON.parse 严格性diff 将输入视为不透明文本。如果某次捕获包含尾随逗号、未加引号的键或注释(严格 JSON 中均不合法),它仍会进行 diff,但会比必要的更嘈杂。先将两次捕获都通过 jq . 处理,以重新格式化并拒绝无效输入。jq 使用严格的 RFC 8259 解析器。
响应包装(data 信封与平铺结构)许多 API 将响应包装在 {"data": ...} 信封中,有时还附带 metalinksincludedJSON:API 及类似规范)。从平铺结构迁移到包装结构(或反向)是一个破坏性变更,在 diff 中立即显现,但在 schema 审查中容易被忽视,因为底层记录看起来相同。
分页游标变化基于游标的分页使用不透明令牌(next_cursorafterpage_token),这些令牌在每次调用时都会变化,总是会显示为 diff。比较前先删除它们,或只比较 data 数组的内容,忽略分页块。
错误响应格式错误响应格式各异。有些 API 返回扁平的 {"error": "..."},有些返回带有 typetitlestatusdetailinstanceRFC 7807 Problem Details,有些则返回自定义格式。从自定义格式迁移到 RFC 7807 会产生较大的 diff,但通常是一种改进;反向迁移则是值得早期发现的回归。

API 响应 diff:常见问题

这与 Postman 内置的 diff 功能有什么不同?

Postman 在 Collection Runner 中有响应比较视图,也有针对单个响应的 Visualize 功能。如果您使用 Postman 并且响应已保存为 Postman 历史记录,这些功能很好用。本工具与平台无关,您可以粘贴来自 Postman、Insomnia、curl、httpie、CI 日志、Stack Overflow 代码片段或同事 Slack 消息中的内容,无需账户、工作区或同步。对于跨工具的一次性比较,这样更快。对于团队在单一平台内共享的 API 测试,Postman 自身的功能没问题。

如何处理时间戳和请求 ID 等易变字段?

实用的做法是在 diff 之前先规范化。在面板中打开两个粘贴内容,直接编辑易变字段:用常量字符串替换时间戳,删除 request_idtrace_id 的值,移除每次调用都会变化的分页游标。diff 只会高亮剩余的差异,这些才是真正重要的。对于同一接口的重复比较,您还可以在粘贴之前通过 jq 加删除过滤器处理响应(jq 'del(.meta.request_id)')。

这与 OpenAPI schema diff 有什么不同?

Schema diff 比较的是契约:它告诉您 POST /orders 新增了可选的 discount_code 字段,或 status enum 新增了一个值。OpenAPI 感知工具(如 oasdiff 或 Spectral)擅长做这件事。本工具比较的是实际响应体。两者互补:schema diff 捕获契约变更,响应 diff 捕获契约与现实之间的漂移,而序列化 bug、环境不一致和过时 fixture 正是藏在这里。

能处理大型响应吗?

实际上可以,每侧最多支持几千行格式化后的 JSON。超过这个范围,带语义清理的字符级 diff 会变慢,因为它在浏览器中运行而非服务器。对于非常大的响应体(比如包含一万条记录的分页数据),正确的做法是按记录或按顶层键将响应切分成小块,分别进行 diff。或者在命令行使用 jddiff <(jq . a.json) <(jq . b.json) 进行结构化 diff 以获得更快的速度。

支持 XML 或 SOAP 响应吗?

不直接支持。本页面针对 JSON 进行了优化,这是大多数现代 REST 和 webhook 响应的格式。如果需要 diff XML、SOAP 信封、RSS 或 POM 格式配置,请使用我们的 compare-xml 工具,它能正确处理缩进和命名空间格式。对于混合了 header 和 body 的原始响应体,或纯文本 API(部分遗留系统仍返回 text/plain),compare-text 不会强制要求特定结构,同样可以胜任。

它保留键顺序还是对键排序?

它保留您粘贴时的键顺序。根据 RFC 8259,JSON 对象在形式上是无序的,因此两个语义相同但键顺序不同的响应在本工具中会显示为 diff。如果想忽略顺序,请先通过 jq --sort-keys 或等效工具对两侧进行规范化。大多数客户端不依赖键顺序,因此排序规范化对于响应比较是安全的默认选项;但请注意,某些遗留消费者(旧版 XML-to-JSON 桥接器、特定数字签名流程)确实依赖顺序。

粘贴包含 auth token 或用户数据的响应安全吗?

安全。diff 完全在您的浏览器中运行,不会上传、记录或发送到任何地方。这一点在这里尤为重要,因为真实响应中经常泄漏 Authorization bearer token、Stripe 用户 ID、会话 cookie 和 PII 字段。将这些内容粘贴到服务器端 diff 网站,在 GDPR 或 SOC 2 合规要求下会构成真正的数据处理事件。想要验证?打开 DevTools,粘贴时观察 Network 标签,确认没有任何内容离开页面。

这个工具免费吗?需要注册吗?

免费,无需创建账户。没有试用期,没有席位限制,没有邮件门槛。粘贴两个响应,阅读 diff,关闭标签页。每个按钮——格式化、上传、示例——在首次访问时无需登录即可使用。这是一个单一用途的工具,而非付费漏斗,因此没有隐藏在锁后面的功能层。

能同时比较两个以上的响应吗,比如三个环境?

无法在一个视图中实现,本工具围绕两个面板设计。对于三方比较(例如同一接口在 dev、staging 和 prod 上的响应),分两次运行:dev 对比 staging,再 staging 对比 prod。依次阅读两个清晰的 diff 比眯眼看三列 JSON 更容易。如果确实需要 N 路结构比较,那是命令行用 jqdiff 做的事,而不是粘贴工具。

能上传两个保存的响应文件而不是粘贴吗?

可以。点击任意面板上的上传,选择保存的 .json 文件(例如 curl 输出或已签入的测试 fixture)。浏览器通过 File API 在本地读取,文件不会离开您的设备。上传一侧、粘贴另一侧是常见操作:从磁盘加载已提交的 fixture,从终端粘贴实时响应。没有格式限制,只要是文本就能加载。

离线可用吗?可以在手机上使用吗?

两者都可以。diff 是客户端 JavaScript,不需要服务器调用,因此页面加载后断网仍可继续工作,在锁定的构建机器或不稳定的 VPN 后面很方便。在手机上,两个面板会垂直堆叠,捏合缩放也可以使用,不过密集的 JSON 响应在笔记本上双栏并排阅读确实更方便。

隐私保护与 API 响应数据的重要性

API 响应数据经常包含您不希望泄露的内容:用户邮件地址、内部用户 ID、会话令牌、误入响应体的 Auth bearer token、Stripe 用户 ID、webhook secret、包含姓名、地址和电话号码的 PII 字段。将这些内容粘贴到云托管的 diff 服务中本身就是一次数据处理事件,根据行业不同,可能违反您的 SOC 2 控制要求、GDPR 数据处理协议或 HIPAA 业务伙伴协议。本工具完全在您的浏览器中运行。不上传任何内容,不记录,不发送给任何第三方服务。diff、高亮和渲染都在您的设备上执行。验证这一点很简单:打开浏览器 DevTools,切换到 Network 标签,粘贴两个响应并观察,比较时没有任何出站请求。更多关于 API 设计和安全的指导,可参考微软的 API 设计最佳实践