GraphQL 格式化实战: 把单行 query 美化成可读结构
GraphQL query 和 schema 被压成一行就很难调试。这篇讲怎么把它格式化成每字段一行、缩进对齐的可读结构,定位嵌套层级,看清变量声明,全程在本地浏览器处理。
GraphQL 格式化实战: 把单行 query 美化成可读结构
写 GraphQL 的人都遇到过这一幕: 从 webhook payload、日志、或者某个 HTTP 客户端里抠出来一段 query, 它是单行的, 一千多字节挤在一起, 字段、参数、嵌套全糊成一坨。要看清它在查什么, 先得手动断行、缩进, 这件事本身就够烦的。这篇就讲清楚 GraphQL 格式化到底在解决什么, 以及怎么用 GraphQL 格式化与压缩 把这类输入还原成能读、能调的结构。
单行 query 为什么读不动
GraphQL 的语法对换行和缩进没有强制要求, 一段 query 写成一行也完全合法。问题是, 选择集 (selection set) 是可以无限嵌套的: 一个 user 下面挂 posts, posts 下面挂 comments, comments 里又挂 author。这种嵌套关系在多行带缩进时一眼就能看出层级, 压成一行后, 你只能靠数大括号来判断自己在第几层。人脑数大括号的准确率, 三层以上就开始崩。
格式化要做的, 就是把每个字段单独放一行, 按嵌套深度给出缩进, 让结构重新可见。
一个真实的输入输出例子
下面这段是压成一行的查询, 现实里 webhook 或日志里抠出来的就长这样:
query Feed($cursor:String,$limit:Int=20){user(id:"u_42"){name posts(after:$cursor,first:$limit){edges{node{id title comments{author{name}}}}}}}
格式化之后:
query Feed($cursor: String, $limit: Int = 20) {
user(id: "u_42") {
name
posts(after: $cursor, first: $limit) {
edges {
node {
id
title
comments {
author {
name
}
}
}
}
}
}
}
现在结构清楚了: posts 是 user 的子字段, comments 嵌在 node 里, 最深处的 author { name } 一共第七层缩进。变量 $cursor: String 和 $limit: Int = 20 也从 operation 头部里被拎出来, 类型和默认值一目了然, 想构造一份匹配的 variables JSON 不用回头再读头部。
缩进对齐与嵌套层级
缩进不是装饰, 它是 GraphQL 可读性的核心。每深一层选择集, 缩进就多两个空格 (也可以选 4 空格或 Tab), 字段与它的父字段在视觉上对齐成一条阶梯。调试一个返回结构不对的查询时, 你最先要确认的就是"我有没有把字段挂错层", 比如本该在 node 下的字段被写到了 edges 下。对齐好的缩进让这种错位直接暴露在眼前, 不用再逐个括号配对。
参数也一样。短参数同行写在 ( 后面, 长参数列表换行排开, 这是 Apollo 和 VSCode 插件的默认风格, 把结果粘回 .graphql 文件不会触发 linter 误报。
schema (SDL) 也能格式化
很多人以为格式化只对 query 有用, 其实 schema 定义语言 (SDL) 更需要。从网关拉下来的 printed schema 经常是一大坨文本, type、interface、union、enum、input 全挤在一起。格式化后每个定义独立成块, 字段对齐, 注释保留在原来的位置。手改完 SDL 准备 push 之前, 先粘进来跑一遍, 如果有个多余的冒号或括号没配对, 解析器会精准报出行号、列号, 还附上前后三行源码上下文, 比 CI 里那句含糊的 "unknown token at offset 1284" 友好得多。
我自己的用法
我平时排查接口问题, 第一步几乎都是把抓到的单行 query 丢进格式化器。有一次线上某个列表接口返回的数据比预期少了一层, 我把 query 格式化开后立刻看到: comments 字段缩进错了, 被挂到了 edges 而不是 node 下面, 单行状态下我盯了五分钟都没发现。格式化只花了三秒, 比开 Node REPL 跑 print(parse(x)) 快得多, 也不用为了跑一次就 npm install graphql。
调试 GraphQL 时还有个常被忽略的坑: 从 wire 格式里抠 query。HTTP body 经常长这样 {"query": "..."}, 这是一层 JSON 外壳, 格式化器只认裸 GraphQL。先用 JSON 格式化工具 把 query 字段的值抠出来, 再丢进 GraphQL 格式化器, 两步就到位。
本地处理, 生产 query 也能放心粘
最后说一句安全。生产环境的 query 里常常带着内部字段名、auth header 引用、甚至 PII 参数值, 这些东西不该上传到任何服务器。这个格式化器的解析是一段大约 400 行的手写递归下降, 完全在你的浏览器标签页里跑, 没有引入 graphql-js, 没有任何网络请求, 也不会去远程拉 schema。格式化时打开 DevTools 的 Network 面板看, 一个带 query 内容的请求都不会发出。URL 里只同步选项 (缩进、排序、模式), query 本身永远不写进 URL, 所以分享链接也不会泄露查询内容。
把 GraphQL 格式化当成调试的第一步, 很多看不出来的结构问题会自己浮上来。
Made by Toolora · Updated 2026-06-13