🎏:你只管努力,剩下的交给时间
🏠 :小破站
前言
两篇文章下来,环境搭好了,也写了个TODO工具。但说实话,那个TODO工具虽然能用,但使用频率可能不高。
这次我们来做个真正高频使用的工具:JSON格式化处理工具。为什么说高频?因为只要你是程序员,几乎都要处理JSON。
传统方式的痛点
作为开发者,你肯定遇到过这些场景:
场景1:调试API
1. Postman返回一坨压缩的JSON
2. Ctrl+C 复制
3. 打开浏览器
4. 搜索"JSON formatter"
5. 粘贴JSON
6. 点击"Format"
7. 再复制回来
场景2:压缩配置文件
同样的流程,只不过点的是"Minify"按钮
还要担心网站是否保存了你的数据
每次都要这么折腾! 要是JSON有语法错误,还不告诉你具体哪里错了。
我们的解决方案
# 复制API返回的JSON后
jsonf format
# 完成!格式化结果已在剪贴板
就这么简单!
- 不用打开浏览器
- 不用访问网站
- 不用手动粘贴
- 结果自动复制到剪贴板
这才是程序员真正需要的工具。
项目设计
核心功能
我们要实现4个命令:
- format - 格式化(美化)JSON
- minify - 压缩JSON
- validate - 验证JSON语法,精确指出错误位置
- analyze - 分析JSON结构统计
最大亮点
智能输入源检测:
- 提供文件路径 → 从文件读取
- 管道输入 → 从stdin读取
- 啥都不提供 → 自动从剪贴板读取 ⭐
自动输出到剪贴板:
- 处理完的结果自动复制
- 直接粘贴使用
- 省去手动复制步骤
技术选型
- serde/serde_json - JSON序列化,Rust生态的标准
- arboard - 跨平台剪贴板操作
- colored - 彩色终端输出
- clap - 强大的CLI参数解析
第一步:创建项目
cargo new json_formatter
cd json_formatter
ls -la
可以看到cargo又帮我们生成了完整的项目结构,包括git仓库。这个习惯真好,每个项目都从一开始就被git管理。
第二步:配置依赖
编辑 Cargo.toml:
[package]
name = "json_formatter"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "jsonf"
path = "src/main.rs"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
colored = "2.1"
arboard = "3.3"
clap = { version = "4.4", features = ["derive"] }
几个要点:
-
[[bin]]配置 - 把可执行文件命名为jsonf,比json_formatter短多了 - serde的derive特性 - 自动生成序列化代码
- arboard - 这是剪贴板操作的关键,跨平台支持Mac/Linux/Windows
- clap的derive特性 - 用宏自动生成命令行参数解析
第三步:命令行结构设计
用clap定义命令结构非常优雅:
#[derive(Parser)]
#[***mand(name = "jsonf")]
#[***mand(about = "JSON格式化工具 - 美化、压缩、验证JSON")]
struct Cli {
#[***mand(sub***mand)]
***mand: ***mands,
}
#[derive(Sub***mand)]
enum ***mands {
Format {
file: Option<String>,
#[arg(long)]
no_copy: bool,
},
Minify {
file: Option<String>,
#[arg(long)]
no_copy: bool,
},
Validate {
file: Option<String>,
},
Analyze {
file: Option<String>,
},
}
这里的设计很巧妙:
-
file: Option<String>- 文件路径是可选的 - 不提供 = 从剪贴板读取
- 提供了 = 从文件读取
-
no_copy选项可以禁用自动复制到剪贴板
第四步:编译项目
cargo build
第一次编译会下载很多依赖,花了13秒多。可以看到下载了:
-
serde、serde_json- JSON处理 -
arboard- 剪贴板 -
colored- 彩色输出 -
clap相关的一堆库
编译完还有2个警告:
warning: unused import: `json`
warning: unused variable: `indent`
Rust编译器 - 严格但友好
这就是Rust的特色。其他语言(Python、JavaScript、Go)不会提示这些:
# Python - 静悄悄通过
import json # 导入了但没用
def process(data, indent): # indent没用
pass
Rust不允许。它会告诉你:
- 哪里有问题(第几行第几列)
- 具体什么问题(未使用的导入/变量)
- 怎么修复(给出建议)
为什么这么严格?
- 帮你写出更干净的代码
- 避免潜在的bug(可能是你忘记用了)
- 减少代码腐化
这就是Rust的哲学:“如果编译通过了,大概率就不会出bug”。
按照提示修改代码,重新编译就干净了。这个过程让你的代码质量更高。
第五步:准备测试数据
创建三个测试文件:
- test.json - 正常的JSON,但格式混乱
- messy.json - 压缩成一行的JSON
- error.json - 有语法错误的JSON
这三个文件覆盖了典型场景:格式化、压缩、错误检测。
第六步:查看帮助信息
cargo run -- --help
cargo run -- format --help
clap自动生成的帮助文档非常专业:
- 清晰的用法说明
- 每个命令的描述
- 参数说明
这就是用框架的好处,不用自己写帮助文档。
第七步:测试格式化功能
cargo run -- format test.json
效果非常棒!
可以看到:
- JSON被美化了,缩进清晰
- 彩色输出 - key是蓝色,值根据类型有不同颜色
- 显示"已复制到剪贴板"
- 显示字符数统计
对比原始文件:
// 原来是一坨
{"name":"张三","age":25,"skills":["Rust","Python","JavaScript"],...}
// 格式化后
{
"active": true,
"address": {
"city": "北京",
"district": "朝阳区"
},
"age": 25,
...
}
核心实现:彩色输出
代码里用了 colored 库:
println!("{}", key.cyan().bold()); // 键名青色加粗
println!("{}", string.green()); // 字符串绿色
println!("{}", number.yellow()); // 数字黄色
println!("{}", boolean.magenta()); // 布尔紫色
让输出更容易阅读,一眼就能看出JSON结构。
第八步:测试压缩功能
cargo run -- minify messy.json
压缩结果直接输出成一行:
{"items":[{"id":1,"price":99.99},{"id":2,"price":199.99}],"name":"测试用户","total":299.98}
还显示了压缩统计:
- 原始大小
- 压缩后大小
- 减少百分比
这对于优化配置文件大小很有用。同样,结果已经自动复制到剪贴板。
第九步:测试错误检测
cargo run -- validate error.json
这是最厉害的功能!
对于有错误的JSON:
{
"name": "测试",
"age": 25,
"invalid": // ← 缺少值
}
我们的工具会:
- 精确定位:第5行,第1列
- 显示上下文:把错误附近的代码列出来
- 用红色标记错误行
- 用箭头指出具体位置
对比其他工具:
- 浏览器JSON工具:只说"语法错误",不告诉你哪里错
- Python json.loads:报错信息不友好
- 我们的工具:精确到行列,还显示上下文
这就是Rust生态的优势,serde_json 的错误信息质量很高。
第十步:剪贴板功能 - 最实用的特性!
这是最核心的功能,也是最大的创新点。
使用流程
# 1. 在任何地方复制一段JSON(Cmd+C)
# 2. 运行命令
cargo run -- format
# 3. 完成!结果已在剪贴板
工具会自动检测:
- 显示"📋 从剪贴板读取…"
- 处理JSON
- 显示格式化结果
- 显示"📋 已复制到剪贴板"
实现原理
这是通过 arboard 库实现的:
use std::io::IsTerminal;
fn read_input(file: &Option<String>) -> Result<String, String> {
match file {
Some(path) => {
// 从文件读取
fs::read_to_string(path)?
}
None => {
// 检测stdin是否是终端
if !io::stdin().is_terminal() {
// 从管道读取
let mut buffer = String::new();
io::stdin().read_to_string(&mut buffer)?;
Ok(buffer)
} else {
// 从剪贴板读取
let mut clipboard = Clipboard::new()?;
clipboard.get_text()?
}
}
}
}
智能三路判断:
- 提供了文件参数 → 文件读取
- 是管道输入 → stdin读取
- 否则 → 剪贴板读取
这就是为什么我们的工具这么灵活:
jsonf format file.json # 方式1:文件
cat file.json | jsonf format # 方式2:管道
jsonf format # 方式3:剪贴板 ⭐
第十一步:安装到系统
现在我们要让工具全局可用。
编译release版本
cargo build --release
release版本会进行优化:
- 编译时间长一点
- 但生成的二进制更小、更快
- 没有调试信息
安装到系统
sudo cp target/release/jsonf /usr/local/bin/
把编译好的可执行文件复制到系统路径。
验证安装
which jsonf
# 输出:/usr/local/bin/jsonf
现在可以在任何地方使用了!
实际使用
从截图可以看到,安装后直接用 jsonf 命令:
# 复制一段JSON后
jsonf format
# 输出彩色格式化结果
# 自动复制到剪贴板
还测试了 minify:
jsonf minify
# 输出:{"items":[{"id":1,"price":99.99}...]...}
完美!工具已经真正可用了。
总结
通过这个项目,我们:
做了什么
- ✅ 实现了一个完整的JSON处理工具
- ✅ 支持格式化、压缩、验证、分析
- ✅ 核心创新:剪贴板自动读写
- ✅ 跨平台支持
- ✅ 安装到系统,全局可用
学到了什么
- 系统级编程 - 剪贴板操作、stdin检测
- 跨平台抽象 - 一份代码到处运行
- CLI设计 - clap框架的强大功能
- 错误处理 - Rust的Result和map_err
- 用户体验 - 彩色输出、清晰提示
- release编译 - 生产级别的优化
解决了什么问题
彻底改变了JSON处理的工作流:
旧方式:复制 → 打开浏览器 → 找网站 → 粘贴 → 格式化 → 复制回来
新方式:复制 → jsonf format → 完成
这才是真正实用的工具。
Rust的价值
这个项目充分展示了Rust的优势:
- 安全 - 编译器保证没有内存问题
- 高性能 - 原生可执行文件,启动快
- 跨平台 - 轻松支持Mac/Linux/Windows
- 生态好 - arboard、clap、serde等库质量高
- 开发体验 - 错误提示友好,重构容易
实用建议
创建别名
把这个加到 ~/.zshrc:
alias jf="jsonf format"
alias jm="jsonf minify"
alias jv="jsonf validate"
然后就可以:
jf # 格式化剪贴板中的JSON
jm # 压缩
jv # 验证
配合其他工具
# 格式化curl结果
curl https://api.github.***/users/rust-lang | jf
# 查看Docker inspect结果
docker inspect container_id | jf
# 格式化git配置
cat .git/config | jf
日常工作流
我现在的JSON处理流程:
- API返回JSON → 复制
-
jf→ 格式化 - 粘贴到代码里
快到飞起!
做完这个工具,你真的会每天用它。 这就是学编程的意义:解决实际问题,提高工作效率。
Rust让我们能写出这样的工具:安全、快速、跨平台。继续探索Rust,你会发现更多可能性。