简介Geany-JSON-Prettifier 是专为 Geany 编辑器打造的 JSON 处理插件帮助 Linux 开发者直接在编辑环境中完成格式化、压缩、验证和局部美化适用于日常调试配置、API 响应分析及批量 JSON 整理等场景。压缩包为 zip 类型包含 176 个文件其中 C 源码、头文件、JSON 测试样例、gold 预期结果及 CMake/configure 构建脚本是主体整体大小仅 163KB下载成本低且适合离线研究。功能上它不仅支持整体与选中部分的格式化/压缩还能在一个文件内区分多个 JSON 实体并统一美化缩进方式可选空格或制表符斜杠转义也支持配置。同时源码以 yajl 解析器为核心搭配 Geany 插件接口便于学习 C 语言插件开发与 JSON 解析逻辑。目前已有 401 人浏览学习适合作为开发者提升编码效率的轻量工具也适合作为 Geany 扩展开发的参考范例。 写博文之前先聊聊背景。我平时重度依赖轻量级编辑器Geany 一直是我处理脚本和配置文件的主力工具。但有一件事长期让我难受手边临时要美化一段 JSON、压缩一段接口响应、或者验证一份手写的配置文件时Geany 默认并没有这些能力每次都得切到命令行、打开在线工具或者启动一个笨重的 IDE。这个 Geany-JSON-Prettifier 插件就是专门解决这类型的问题的——在 Geany 里直接完成 JSON 的美化、缩小和验证不用离开编辑器。适合谁天天用 Geany 写代码、调接口、折腾配置文件的开发者尤其是不想为一个小功能单独装一个重型工具的人。1. 这个插件解决什么问题1.1 轻量级编辑器做 JSON 处理的尴尬Geany 是一款启动极快、依赖极少、跨平台的编辑器很多人拿它当 Notepad 的替代品或者配合轻量脚本环境使用。但正是这种轻导致它默认只带基础编辑功能。JSON 文件的场景看起来很单纯实际用起来全是细节从网页控制台复制的 JSON 常常是一整行挤在一起根本没法阅读从接口服务端拿到的返回报文里可能混杂了错误信息、多了尾随逗号甚至包含 BOM 头自己写的配置文件少写一个逗号或者引号不匹配就会导致后续程序解析失败。这些事单独拎出来都不难正则替换、在线格式化、写个小脚本都能做。可一旦变成高频操作来回切换上下文的成本就很可观。我这个插件的原始需求就是这么出来的把验证、美化、缩小这三件最常用的 JSON 处理动作直接放进 Geany 的右键菜单和快捷键体系里。能用最快的路径完成数据不离开本地文件不依赖网络也不会被某些在线工具偷偷拿去存你的数据。1.2 三个功能不是三个独立按钮而是一条流水线很多人拿到一个 JSON 格式化插件会以为美化器和缩小器是两个割裂的功能。实际上它们共享同一个底层解析核心。整个插件的工作流应该是先验证、再转换、最后覆盖写入。美化器负责重排缩进和换行缩小器负责去掉所有非必要的空白而验证器负责在前两步执行之前确认文件是不是合法的 JSON。这三个能力放在一起还有一个额外价值当你从一个不可信来源粘了一段疑似 JSON 的东西先跑一遍验证器它能告诉你是真正的 JSON、还是某个网页返回的错误信息、又或者只是拼接了一半的内容。我自己多次靠这一步避免把错误数据当正常数据去处理。如果文件非法美化器和缩小器会拒绝执行并弹出错误提示而不是像某些编辑器那样把损坏的内容直接格式化输出等于给后续操作上了一道安全闸门。2. 核心实现思路与技术拆解2.1 为什么不能靠正则表达式硬处理第一版我确实偷懒过想用一个巨大的正则表达式做缩进匹配核心思路是把{、[、,后面加换行再根据嵌套深度补空格。测试简单样本一切正常直到遇见一个 JSON 字符串值里恰好包含了: 这种字符组合比如{error: message: {not_json}}。正则硬上直接把这个字符串内部的内容也换行了整个文件当场报废。所以很关键的一个设计决策是不管美化、缩小还是验证必须先做真正的 token 解析把 JSON 内容拆成结构化的 token 流而不是在原始字符流里做字符匹配。JSON 的 token 集合其实不大六个结构字符{ } [ ] : ,加上字符串字面量、数字字面量、布尔字面量、null 字面量。用一层递归下降解析器就能覆盖。typedef enum { TOKEN_BRACE_OPEN, TOKEN_BRACE_CLOSE, TOKEN_BRACKET_OPEN, TOKEN_BRACKET_CLOSE, TOKEN_COLON, TOKEN_COMMA, TOKEN_STRING, TOKEN_NUMBER, TOKEN_TRUE, TOKEN_FALSE, TOKEN_NULL, TOKEN_EOF, TOKEN_ERROR } JsonTokenType;这是插件内部 token 类型定义的简化版本。只要解析器跑通一遍确认 token 序列能完整匹配 JSON 语法规则后续的美化和缩小就都建立在语法树或 token 流之上不再有误伤字符串内部内容这类问题。2.2 美化器的三个关键细节缩进、排序、数组策略美化器在不同编辑器里的表现差异很大原因不是换行算法难而是细节策略不同。我在实现里重点处理了三件事。第一是缩进宽度不能写死。Geany 本身是支持 Tab 缩进和空格缩进的如果插件强行固定成四个空格会跟用户当前的编辑习惯冲突。插件的配置界面里我保留了从 Geany 主配置读取缩进模式的逻辑如果 Geany 设置为 tab 缩进插件就用真实 Tab 键否则按用户设定的空格数展开。这样处理完之后文件能无缝融入原有代码风格。第二是键排序默认保持原序但提供可选按字母排序。JSON 标准里对象是无序键值对集合但实际工程中很多配置文件依赖书写顺序。默认不排序是最稳妥的因为格式化不应该改变数据的物理组织方式。可选项给那些喜欢规整风格的人尤其是想把日志里提取出来的散乱 JSON 整理成统一风格时按字母排序确实更好扫。第三是数组内对象的换行策略。默认情况下数组元素如果是对象每个对象占一行如果是数字、字符串每行放一个值。实践证明全展开是最稳妥的因为紧凑模式和展开模式之间语义完全一致但阅读体验差异巨大。我在配置里加了紧凑数组模式开关满足那些追求高信息密度的人。2.3 缩小器实现时最容易踩的坑缩小器的目标是把文件压缩成最小体积去掉空格、换行、制表符但字符串内部的空白必须原样保留。这一条正是第一版正则方案翻车的根源。换成基于 token 流的实现之后缩小器只需要按 token 重新拼接输出即可结构字符之间不加空格冒号后面不加空格逗号后面不加空格字符串内部的字符原样输出。还有两个边界细节需要注意。空对象{}和空数组[]内部不需要任何空白即使在字符串连接时也要保持紧凑。另一个是数字处理JSON 数字不区分整数和浮点但缩小器不能改变数字的原始语义比如1不能变成1.0也不能变成1e0直接保留 token 源的原始文本最省事。// 缩小器输出逻辑的核心思路 void minify_token_stream(FILE *output, JsonToken *tokens, int count) { for (int i 0; i count; i) { switch (tokens[i].type) { case TOKEN_STRING: case TOKEN_NUMBER: case TOKEN_TRUE: case TOKEN_FALSE: case TOKEN_NULL: // 原样输出字面量内容 fwrite(tokens[i].start, tokens[i].length, 1, output); break; case TOKEN_COLON: case TOKEN_COMMA: // 直接输出不追加空白 fputc(tokens[i].text[0], output); break; default: // 括号类结构字符直接输出也不追加空白 fputc(tokens[i].text[0], output); break; } } }2.4 验证器要做到报错报到位普通插件能告诉你JSON 解析失败但作为日常工具这远远不够。一个三千行的配置文件只知道失败是没用的必须知道失败在哪一行、哪一列、期望什么、实际得到什么。这个插件在错误信息上专门做了结构化输出行号、列号、期望的 token 类型、实际遇到的字符内容。以最常见的错误为例对象中写漏了冒号。解析器读取完键名后期望的下一个 token 是:但实际可能是,或者直接是另一个字符串。此时验证器会生成一条错误Expected : after property name, got , at line 6, column 10。Geany 的消息窗口能自动把这一行解析出来点击就可以跳转到错误位置。这个体验确实比盲目查找好太多——多行 JSON 嵌套层级深的时候人眼很难一眼看出是第几层缺了括号。验证器的另一层作用是对 BOM 头和编码问题的兜底。很多 Windows 工具会在文件开头插入 UTF-8 BOM严格 JSON 标准不认可这个前缀。插件默认会跳过第一个 BOM 标记避免合法文件被误判。3. 编译安装与日常使用3.1 环境准备与编译流程这个插件是 C 写的依赖 Geany 的插件开发接口和 json-c或自带一个极简 JSON 解析器看版本。如果从源码编译建议先确认系统的依赖是否齐全。Debian/Ubuntu 系大概需要这几种包geany-dev、libjson-c-dev、make、gcc。Fedora 系则是对应geany-devel、json-c-devel。# Debian/Ubuntu 环境示例 sudo apt install geany-dev libjson-c-dev build-essential make make install安装完成后插件文件会放到 Geany 的插件目录里。重新打开 Geany通过菜单工具 → 插件管理器打开对话框勾选JSON Prettifier即可启用。启用后菜单栏会出现一个JSON子菜单集中放置三项操作。Windows 环境如果不想碰编译可以直接拿别人编译好的 DLL 丢进插件目录或在 MSYS2 环境里自行编译两条路都能走通。3.2 配置快捷键把操作变成肌肉记忆命令行工具和 IDE 插件最大的区别在于命令行每次都要先保存文件、切终端、输命令、回编辑器看结果。插件的好处是快捷键直达。默认键位我设置成了三组互为关联的组合格式化用CtrlAltF缩小用CtrlAltShiftF验证用CtrlShiftV。前缀相同便于记忆。如果与 Geany 自带的快捷键冲突可以打开编辑 → 偏好设置 → 快捷键页面在插件分类下找到这三个命令重新绑定。实际操作中我更建议把验证绑定到一个特别顺手的键位上因为它的使用频率往往比格式化更高。3.3 三个真实使用场景复盘场景一格式化接口返回报文。一次调试 Webhook 时对方服务直接把 JSON 响应打印在一行里加前导时间戳和日志级别混在一起完全不可读。我先手动复制 JSON 片段到新文件CtrlShiftV验证合法CtrlAltF格式化几毫秒内变成了结构清晰的层级缩进。定位字段的速度提升了不止一个量级。场景二压缩配置发送给远程服务器。一些部署脚本要求配置文件必须写成单行如果直接手写很容易漏掉换行转义。我一般先写成格式良好的 JSON 文件再一键缩小然后在文件顶部手动补上环境变量语法。这个过程同样耗时极短而且因为没有人工删空白字符串内容完全不会损坏。场景三校验手写配置。有一次手写一个包含五层嵌套的配置文件写完保存后运行程序提示 JSON parse error但没告诉在哪个位置。用插件的验证器一跑直接定位到第 41 行第 16 列少了一个逗号。如果让我对着缩进数括号估计得花好几分钟。4. 常见问题与排查技巧实录4.1 插件在插件管理器里看不到常见原因是插件安装目录不正确或者 Geany 版本过旧。Geany 插件接口在 1.35 前后有过改动如果插件报无法加载动态库先确认 Geany 版本是否满足依赖要求。另一个因素是平台相关Linux 下插件扩展名是.soWindows 下是.dll放错目录或者文件名带后缀不对会导致加载失败。排查思路是先试终端运行geany -v看加载插件时有没有报错消息。如果看到undefined symbol之类的错误基本可以确定是编译时 Geany 版本与运行时版本不一致需要重新针对当前 Geany 版本编译。4.2 格式化后中文变成乱码或转义序列这个问题的根源通常不在插件而是文件编码与插件内部字符串处理不匹配。插件内部解析时统一按 UTF-8 处理如果原文件是 GBK/GB18030 编码解析器会把中文字节逐个当成字符串一部分输出表面上乱码其实是字节序被当成了 Unicode 码点。解决方式很简单处理前先把文件另存为 UTF-8 编码Geany 的状态栏有当前编码显示切换编码后再跑美化一切正常。另一种情况是 JSON 字符串里的 Unicode 转义序列比如\u4f60\u597d。美化器默认会原样保留这些转义不做解码因为转码操作有语义风险。如果希望显示成中文需要额外打开解码 Unicode 转义配置项。4.3 大文件处理慢怎么办插件在处理几百 KB 到几 MB 的文件时没什么压力但超过 20MB 的文件递归下降解析器可能会明显卡顿。排查时先确认是不是每次按键都重新解析整个文件并全量重写这是导致慢的主要因素。当前版本的优化方向是只对选中区域做格式化或者先运行验证器定位到局部错误。如果只是想快速校验大文件语法建议直接跑 CLI 工具比如jq把插件留给常规编辑场景。4.4 与其他插件的快捷键冲突Geany 生态里还有 XML tools、HTML 格式化这类插件它们大多也用CtrlAlt前缀的组合键冲突概率不低。出现快捷键没反应的情况时不用先卸载插件打开快捷键设置页面查看冲突状态即可。我的习惯是统一风格JSON 相关的全部放到CtrlAltShift前缀下最大化减少碰撞可能。4.5 验证器对特殊字符误报少数情况下文件中包含不可见字符比如零宽空格肉眼完全看不到但验证器会报错unexpected character。这种字符常常是从网页复制内容时混进来的。遇到这种情况先开启 Geany 的显示空白字符功能把光标移动到错误位置附近如果疑似存在零宽字符直接删除重打即可。这里也提醒自己网上的 JSON 片段尽量整理后再使用不要指望插件能纠错所有复制脏数据。我个人实际使用下来的体会是这个插件最有价值的反而不是美化而是那个验证器。以前写完配置总带着一丝不确定现在我习惯性地CtrlShiftV一下心里就踏实了。最后再分享一个后续可以扩展的方向如果能把格式化输出的缩进宽度做得像 Prettier 那样支持多套风格预设再配合 snippet 快速插入常见 JSON 结构这个小工具就差不多能覆盖 JSON 日常处理的全部场景了。本文还有配套的精品资源点击获取