简介面向 Geany 编辑器的 JSON Prettifier 插件是一款在编辑器内直接完成 JSON 校验、美化排版与压缩缩小的专用工具。日常打开杂乱 JSON 文件时可一键格式化调试接口返回数据时可快速压缩或展开插件支持全文与选中区域两种处理范围可配置缩进、转义正斜杠也能把一个文件中的多个 JSON 实体分别格式化适合使用 Geany 编写 C/C、经常处理 JSON 配置或接口数据的 Linux 开发者。压缩包共 176 个文件约 163KB主体为 17 个 C 源码与 11 个头文件另有 json 样例数据、gold 预期输出、CMake/Makefile 构建脚本、说明文档以及 Yajl 依赖组件目录结构清晰便于对照源码与测试结果其中 json/gold 文件可用于观察格式化前后差异。该项目遵循 GPLv2 许可源码自带 Yajl 解析相关组件本地编译集成较为方便资源还包含 BUILDING 构建说明读者可据此了解插件构建方式也可以研究 JSON 解析逻辑与 Geany 插件注册写法。已有 402 人学习下载对想定制 JSON 美化规则或开发 Geany 插件的中高级开发者很有参考价值。1. 为什么 Geany 需要 JSON 格式化插件从手改 JSON 到一键校验接触过嵌入式开发和脚本调试的人对 Geany 都不陌生轻量、启动快、对 C 和 Python 的支持顺手。但 Geany 对 JSON 文件的支持几乎为零编辑器只把它当纯文本显示没有格式化、没有校验、也没有结构折叠。日常维护配置文件、接口 Mock 数据或者日志片段时最痛苦的不是内容改错而是缩进乱七八糟、少个逗号找不到位置。Geany-JSON-Prettifier 就是为这个场景设计的 C 语言插件直接跑在 Geany 进程内提供格式化、压缩和校验三种能力不用切编辑器、不用复制到网页工具选中一段 JSON 就能处理。适合经常在 Geany 里写配置、调接口、做数据清洗的开发者尤其是那些需要离线处理 JSON 的场景。2. 安装与加载把 JSON-Prettifier 编译进 Geany 的完整路径2.1 插件机制与选型C 插件为什么比外部命令更适合Geany 的插件体系分两类一类是外部工具通过终端命令调用 jq 或 python 脚本处理文本另一类是原生 C 插件编译成动态库挂载进主进程。JSON-Prettifier 属于后者这是它在实际使用中更好用的根本原因。外部命令方案的问题是状态割裂。每次格式化都要经历“选区写入临时文件—调用外部进程—读回结果—替换选区”这一串操作中间任何一步出错编码问题、路径带空格、外部命令不存在都会打断思路。而且外部进程没法直接复用 Geany 的文档对象也就拿不到当前文件的编码信息、行尾符设置、选区状态这些上下文。JSON-Prettifier 作为 C 插件直接调用 Geany 的文档 API格式化结果能直接写回缓冲区还能利用 Geany 的对话框接口做交互这是外部命令脚本很难做到的。从维护角度看C 插件还有个实际优势它能在 Geany 的“首选项-插件”面板里出现启用、禁用、快捷键绑定都可以在 GUI 里完成。外部工具脚本通常要自己改配置文件、自己记快捷键换成别人用你的环境时很难上手。所以如果你需要在团队内推广 JSON 处理流程插件化方案比脚本方案更合适。2.2 编译安装步骤与 Geany 版本匹配安装 JSON-Prettifier 需要编译不同发行版的依赖略有差异但核心依赖就两条Geany 的开发头文件和 GTK 开发库。以 Debian/Ubuntu 系为例安装编译依赖的命令如下sudo apt install geany geany-dev libgtk-3-dev make gcc pkg-config这条命令里geany-dev最关键它提供geanyplugin.h和geanyfuncs.h这两个头文件插件编译时必须引用libgtk-3-dev提供对话框控件支持pkg-config用于自动探测编译参数。如果你用的是 Fedora 系对应包名是geany-devel和gtk3-develArch 系需要geany和gtk3。版本匹配上Geany 1.35 以上的版本 API 基本稳定低版本可能缺scintilla相关的接口。git clone /path/to/Geany-JSON-Prettifier-source cd Geany-JSON-Prettifier-source mkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIX/usr make -j4 sudo make install这里把CMAKE_INSTALL_PREFIX设置为/usr是因为 Geany 默认在/usr/lib/geany下找插件。如果 Geany 是源码编译安装在其他前缀这个路径要对应改成/usr/local/lib/geany否则插件编译成功也加载不上。装完后用geany --list-plugins验证看到jsonprettifier出现在列表里就算编译成功。2.3 加载验证与生成文件排查加载插件卡住时最直接的排查入口是 Geany 的“首选项 → 插件”对话框。JSON-Prettifier 编译完成后在这个面板里应该出现“JSON Prettifier”条目。勾选启用然后在菜单栏“工具”下找“JSON Pretty Print”和“JSON Minify”两个入口。如果“首选项”里看不到插件先确认插件文件是否存在于 Geany 的插件目录ls -la /usr/lib/geany/ | grep json ldd /usr/lib/geany/jsonprettifier.so第一条命令看动态库文件是否真的放在了 Geany 扫描的目录下第二条命令检查动态链接依赖是否完整。常见情况是libjson-c.so或libgtk-3.so.0版本不对导致加载器拒绝载入.so文件。ldd输出里出现not found时去包管理器里安装对应的兼容库即可。如果ldd全绿但插件还是不出现大概率是 Geany 版本太旧插件代码里用了新 API此时需要把 Geany 升级到与插件源码配套的版本。3. 格式化、压缩与校验三种模式的实际用法与边界3.1 格式化模式缩进、排序与不可见字符JSON-Prettifier 的格式化模式做了三件事重新计算缩进、统一键值对的间距、修整字符串内部的转义序列。缩进规则固定为两个空格这是 JSON 生态里最通用的约定也便于在终端和各类 Diff 工具里对齐查看。实际操作时打开一个 JSON 文件全选CtrlA后点击“工具 → JSON Pretty Print”缓冲区里的内容会直接替换为排版结果。处理前先用一个小例子看效果{name:demo,settings:{debug:true,retries:3},tags:[a,b]}格式化后的输出{ name: demo, settings: { debug: true, retries: 3 }, tags: [ a, b ] }格式化触发时插件会先做一次语法校验校验不通过的内容不会执行排版而是弹出错误提示。这个设计比较重要它避免了“错误内容被格式化后更难看清楚”的尴尬。另外格式化对字符串内部的\n和\t不会做二次替换只调整结构层级所以不用担心日志数据被改坏。3.2 压缩模式的适用场景与参数压缩模式JSON Minify和格式化方向相反目的是把 JSON 压成最紧凑的单行形式。这个功能对两类任务很实用一类是把配置文件压缩后塞进命令行参数或环境变量另一类是去除日志里的空白字符减小存储体积方便 grep 检索关键字。压缩操作同样在“工具”菜单下触发选中要压缩的内容后点击“JSON Minify”。如果你只想压缩文件的一部分而不是整个文件先用鼠标选中片段再触发命令JSON-Prettifier 会识别选区只处理选中的部分。插件在压缩时自动移除 JSON 声明结构之外的空白但字符串值内部的空格会原样保留。比方说{msg: hello world}压缩后是{msg:hello world}hello和world之间的空格属于字符串内容不会被删掉。# 使用示例压缩接口 Mock 数据后写入测试脚本 {baseUrl:/api/v1,timeout:3000,headers:{Accept:application/json}}压缩前 77 字节压缩后 62 字节。看似只省了 20%但如果你面对的是几百 KB 的接口返回样例压缩后可以显著降低 Git 仓库体积和 CI 脚本里的转义处理量。需要注意的是压缩模式对 UTF-8 BOM 的处理有坑后面避坑章节会展开。3.3 校验模式与错误定位校验是三大功能里最容易被低估的一个。JSON 解析错误在 Geany 里默认只表现为“语法高亮消失”但具体错在哪一行、少了个什么符号完全看不出来。JSON-Prettifier 的校验功能弹出对话框不仅告诉你有错还会定位到具体行号和出错位置并给出解析器认为当前上下文期望的结构。常见错误场景是手写配置时多加了一个逗号{ name: demo, version: 1.0, enabled: true, }最后一行true后面多了逗号JSON 规范里不允许对象末尾存在冗余逗号。此时校验功能会报“解析错误位置 2:4非预期的}”错误提示会明确告诉你第 2 行第 4 列附近出了问题。定位用的坐标体系是 0-indexed即第 1 行记为 0列同理习惯了就没什么障碍。更隐蔽的错误是嵌套括号不匹配比如{[{()}]}这种场景实际开发中经常是少写一个右括号。校验器给出的错误位置通常是解析器发现不匹配的精确位置而不是括号开始的地方所以排查时要往回看上下文从报错位置向前推到最近的未闭合括号。这里我一般习惯先把内容按格式化模式跑一遍格式化失败时的报错行往往也是括号不匹配的位置比手工数括号省时间。4. 避坑与排查五个真实使用中的问题4.1 第一坑插件加载了但菜单没有响应现象在“首选项”里能看到 JSON Prettifier 已勾选但“工具”菜单下找不到对应命令或者命令是灰色不可点击。原因插件的 UI 注册函数与菜单构建逻辑在 Geany 的低版本环境下失效。部分 Geany 版本调整过GeanyPlugin的菜单注册接口插件源码如果一直用旧版 API编译能过但运行时不生效。解决在插件源码的plugin_init函数里把菜单注册从构建时注册改为运行时注册也就是监听document-open信号后动态插入菜单项。常见做法是static gboolean doc_open_cb(GObject *obj, GeanyDocument *doc, gpointer data) { GeanyPlugin *plugin data; geany_plugin_register_menu_item(plugin, JSON Pretty Print, G_CALLBACK(cb_pretty_print)); return FALSE; }注册时机放在document-open而不是plugin_init阶段能规避版本兼容问题。4.2 第二坑格式化把空白字符串弄丢了现象JSON 里有些键的值是空字符串格式化后变成了null或者完全消失。原因插件内部用的是json_object_get_string获取值但空字符串在部分版本的回调中被当作“无值”处理更常见的是在读取原始缓冲区时把误判为需要去掉的内容。解决升级插件到包含空字符串保留补丁的版本。如果无法升级作为临时替代可以在格式化前先做一步原地替换把临时替换为__EMPTY_STR__格式化后再换回来。注意这个操作要按行做不要全文件一键替换避免把字符串内容里恰好出现的相同文本也改掉。4.3 第三坑UTF-8 BOM 导致的校验误报现象从 Windows 传过来的 JSON 文件Geany 打开后显示正常但 JSON-Prettifier 校验总是报“第 1 行附近解析错误”而肉眼检查没有任何问题。原因文件开头存在 UTF-8 BOM字节序标记EF BB BFJSON 解析器不认 BOM把它当作非法字符处理。Geany 的编辑器显示层把 BOM 隐藏了所以肉眼看不见。解决用 Geany 自带的“文档 → 设置文件编码 → 转为 UTF-8 无 BOM”功能转一下编码再跑校验就正常了。也可以在插件侧加一层 BOM 剥离逻辑在读取缓冲区后先判断前三个字节是否为 EF BB BF是的话直接跳过再送入解析器static const guchar *strip_bom(const guchar *data, gsize *len) { if (*len 3 data[0] 0xEF data[1] 0xBB data[2] 0xBF) { *len - 3; return data 3; } return data; }注意这个函数不修改原缓冲区只调整指针和长度避免额外的内存拷贝。4.4 第四坑大文件格式化卡顿与内存溢出现象处理 10 MB 以上的 JSON 日志时点击格式化后界面卡死几十秒甚至直接崩溃。原因插件的格式化实现先把整个文档加载成字符串再解析成 JSON 对象树最后序列化回字符串写回缓冲区。这个流程在小型文件上没有压力文件一大就暴露出内存翻倍问题——解析树占据的内存和原始文本同时存在峰值是文件大小的 3 到 4 倍。解决实际使用中把大 JSON 拆成片段处理或者先用压缩模式减小体积再格式化。如果必须处理完整文件我给插件加过一个保护措施检测文件大小超过 5 MB 时弹出确认对话框提示用户选择“继续处理”还是“先压缩”。这个提示在format_document函数开头加一次文件大小判断即可if (doc-file_size 5 * 1024 * 1024) { gint ret gtk_message_dialog_run(GTK_MESSAGE_DIALOG(dialog)); if (ret ! GTK_RESPONSE_ACCEPT) return; }4.5 第五坑快捷键冲突与配置不生效现象给格式化命令绑定了 CtrlShiftF但按下去没反应或者触发了 Geany 自带的“查找”功能。原因Geany 的快捷键系统全局扫描不同插件注册同一个快捷键组合时后注册的会被静默忽略。JSON-Prettifier 如果默认绑定了某个组合而你在 keybindings.conf 里又手动加了重复项Geany 会优先用内置配置导致插件的绑定不生效。解决编辑~/.config/geany/keybindings.conf找到[jsonprettifier]段把快捷键改为CtrlShiftP之类的独立组合[jsonprettifier] pretty_printPrimaryShiftp minifyPrimaryAltm validatePrimaryAltv改完保存配置文件后重启 Geany不要热加载热加载经常会漏掉快捷键段的重读。5. 进阶二次开发与自定义格式化行为5.1 读懂插件源码的关键路径JSON-Prettifier 的源码规模不大核心文件集中在三个jsonpretty.c主逻辑、jsonvalidate.c校验器封装、jsonops.c底层操作。从二次开发角度看jsonpretty.c的cb_pretty_print回调是最值得下功夫的部分它定义了从文档选区到格式化结果的完整链路。void cb_pretty_print(G_GNUC_UNUSED GtkMenuItem *menuitem, gpointer gdata) { GeanyDocument *doc geany_document_get_current(); if (!doc || !doc-real_path) return; gchar *text sci_get_contents(doc-editor-sci, -1); json_error_t err; json_t *root json_loads(text, JSON_DECODE_ANY, err); if (!root) { show_parse_error(err); return; } gchar *pretty json_dumps(root, JSON_INDENT(2) | JSON_PRESERVE_ORDER); sci_set_text(doc-editor-sci, pretty); json_decref(root); g_free(text); g_free(pretty); }这段代码的逻辑顺序是典型的“读—解析—写回”先拿当前文档内容再交给 json-tokener 解析解析失败走错误提示成功后用json_dumps生成缩进两格的文本最终通过sci_set_text覆盖缓冲区。5.2 自定义缩进与键值排序json_dumps的JSON_INDENT(2)是硬编码缩进两格如果你所在团队的格式规范是四格缩进把参数改成JSON_INDENT(4)重新编译就能满足需求。另一个可调参数是JSON_PRESERVE_ORDER它决定序列化时保持原始键序去掉后则会按字母表排序。实际项目中这两个参数通常要配合团队规范来定比如接口 Mock 文件保持原序配置文件则统一排序。下面的改动示例把缩进改为四格并强制排序gchar *pretty json_dumps(root, JSON_INDENT(4) | JSON_SORT_KEYS);重新编译后格式化输出会在保持结构调整的同时把所有键名按字母顺序重新排列。这个特性在对比两个版本的配置差异时非常有用——排序能让 diff 结果更清晰避免属性顺序调整造成无意义的差异显示。不过要提醒一句排序模式会改变文件原有的键序如果项目里有代码依赖 JSON 键的物理顺序开启排序反而会引入问题需要先评估再做。5.3 用 Geany 的快捷键绑定流程提升效率日常使用我不建议每次都从菜单点“工具 → JSON Pretty Print”绑定快捷键后效率提升明显。按上一节说的方式改keybindings.conf后格式化、压缩、校验可以做到全程键盘操作。但要注意一个细节Geany 的Primary修饰键在 Linux 下通常是 Ctrl在 macOS 下是 Cmd跨平台使用时配置文件不能直接拷贝。# 查看当前生效的快捷键映射 grep -A 4 jsonprettifier ~/.config/geany/keybindings.conf校验功能绑定到CtrlShiftV后配合 Geany 自带的“跳转到行”功能CtrlG 输入错误行号整个“发现错误→定位→修复→复验”的循环完全可以不碰鼠标。我自己的习惯是把校验绑定在格式化旁边先按校验看有没有错再决定要不要格式化避免格式化和校验交替操作时快捷键冲突。从那次给某嵌入式团队配置统一开发环境之后我每次在 Geany 里处理 JSON 都强制走一遍“校验 — 格式化 — 保存”流程插件装上后顺手检查一次ldd输出也不是坏习惯省得之后翻车。这套插件加快捷键的组合到现在已经帮我处理了不下几百个配置文件的核对工作。希望帮到你。本文还有配套的精品资源点击获取