mcpField
J
jo

jo

github.com/petr-korobeinikov开发167 次安装2 周前更新
代码仓库

关于 jo

这项面向 Shell 的技能介绍如何用 `jo` 构造 JSON,避免手动处理引号。内容涵盖类型判断、嵌套结构、数组、文件输入和常见命令行用法,并建议对复杂语法查阅手册。

主要功能

  1. 01用 Shell 值构造 JSON
  2. 02推断或强制 JSON 值类型
  3. 03组合嵌套对象和数组
  4. 04读取并嵌入文件内容
  5. 05更新现有 JSON 文档
  6. 06curl 和 kubectl 示例

适用场景

  1. 01用 Shell 变量构造 API 请求体
  2. 02在脚本中生成嵌套 JSON
  3. 03通过命令行修改 Kubernetes 资源

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/petr-korobeinikov/skills --skill jo

安装后在 Claude Code 中输入/jo确认已加载。

附带文件references/options.md

详细介绍

jo

在 Shell 片段中使用 jo 构建 JSON, 而不是手动输入带引号的 JSON 字面量。 jo 会在内部处理 JSON 引号, 因此 Shell 变量可以顺畅展开, 你也不必费心处理嵌套的单引号和双引号。

权威文档: https://github.com/jpmens/jo (README 和 jo.md 手册页)。 依赖任何非简单用法前,请先对照手册确认。

为什么

  • 在 Shell 字符串中手写 JSON,很容易陷入引号转义的泥潭。 在 '{"user":"x"}' 中插入 $VAR,要么会破坏单引号, 要么就得使用难以阅读且容易输错的 '"$VAR"' 模式。
  • 内嵌 JSON 中的拼写错误(缺少逗号、多余引号、尾随逗号) 会在服务端报错, 而不是在解析时就报错 — 在很长的单行负载中很难发现。
  • jo 会根据值推断类型: 数字、布尔值、null、嵌套对象和数组都会自动识别; 如果推断结果不符合预期,可按单词使用 -s/-n/-b 覆盖 (例如必须保留为字符串的数字 ID)。
  • jo 支持组合使用: Shell 变量、命令替换、方括号路径简写 和嵌套的 jo 调用都能使用,无需重新转义。

jo 如何判断值的类型

根据手册页,值的处理流程如下:

  1. 尝试将值解析为 JSON。 5 → 数字, true/false → 布尔值, null → null, {...} / [...] → 嵌入的对象/数组, 看起来像数字但不是有效浮点数的字符串 (例如 3.14159.26)→ 字符串。
  2. 如果 JSON 解析失败, 检查特殊值前缀: @file、%file、:file (见下文的从文件读取)。
  3. 否则,将其视为字面字符串。

缺失/空值(k=)会变成 null。 传入 -B 可禁用对字面字符串 true/false/null 的检测。 全局使用时, -n 会丢弃值为空的键 (不要与 -- 后按单词使用的 -n 强制转换混淆)。

直接替换

不要请使用
'{"name":"alice"}'"$(jo name=alice)"
'{"name":"'"$USER"'"}'"$(jo name="$USER")"
'{"count":5,"active":true}'"$(jo count=5 active=true)"
'{"value":null}'"$(jo value=null)"(或 "$(jo value=)")
'{"tags":["a","b","c"]}'"$(jo tags="$(jo -a a b c)")"
'{"point":[1,2]}'"$(jo 'point[]=1' 'point[]=2')"
'{"geo":{"lat":10,"lon":20}}'"$(jo 'geo[lat]=10' 'geo[lon]=20')"
'{"user":{"id":1,"name":"alice"}}'"$(jo user="$(jo id=1 name=alice)")"
'{"code":"12345"}'(字符串 ID)"$(jo -- -s code=12345)"

方括号路径形式(key[]=、key[sub]=)仅支持一级嵌套 — 'a[b][c]=1' 会静默丢弃 [c],并生成 {"a":{"b":1}}。 如需更深层嵌套, 请通过命令替换使用嵌套的 jo。

语法速查

值的形式
  • k=v — 先按 JSON 解析,再检查前缀,最后作为字面字符串处理 (见*jo 如何判断值的类型*)。
  • k@v — 根据真值生成布尔值 (T/t 或非零数字 → true,否则为 false); 适用于 flag@$ENABLED。
  • k=@file — 将 file 的内容作为字符串值加载。
  • k=%file — 将 file 作为 Base64 编码字符串加载。
  • k=:file — 将 file 解析为 JSON 并嵌入。
  • k:=file 或 k:=- — 与 k=:file 相同,但作为运算符使用; - 表示从标准输入读取 JSON。

如需在字符串值开头使用字面字符 @、% 或 :, 请用 \ 转义: twitter='\@jpmens'、 vimcmd='\:split'、 uri='\\%20'。

方括号路径(一级)
  • 'name[]=v1' 'name[]=v2' — 追加到 name 数组。
  • 'obj[k]=v' — 创建 {"obj":{"k":v}}。
  • 结合 -d. (路径分隔符)使用点号表示法: jo -d. geo.lat=10 geo.lon=20 等同于 jo 'geo[lat]=10' 'geo[lon]=20'。
  • 方括号形式务必加引号 — 未加引号的 [ / ] 会被 zsh 的通配符匹配捕获 (bash 也一样, 只要有任何匹配项)。
数组
  • jo -a v1 v2 v3 — 自动推断类型的值组成的数组。
  • jo -a -- -s 123 hello -n "five" — 在数组内逐词进行类型转换 (此处为:["123","hello",4] — 对非数字字符串使用 -n 会返回其长度)。
类型转换
  • jo -- -s k=v — 强制转换为字符串。 适用于数字 ID、版本字符串、电话号码和邮政编码。
  • jo -- -n k=v — 强制转换为数字 (非数字字符串会转换为其长度)。
  • jo -- -b k=v — 强制转换为布尔值 (空值 → false,其他任何值 → true)。
  • 只要列表中的第一个词以 - 开头, 就必须在词列表前加上 --; 为与手册保持一致,请始终传入它。
全局选项

最常用的两个:

  • -p — 美化输出 (生产环境的请求载荷中应省略)。
  • -a — 输出数组而非对象。

完整选项列表 (-B、-D、-n 全局选项、-d sep、-f file、-e、-o、-v/-V, 以及 -- 后逐词类型转换的语义) 请参阅 references/options.md。

惯用写法

使用 curl 发送带请求体的 POST:

curl -X POST https://api.example.com/v1/users \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "$(jo name="$NAME" email="$EMAIL" active=true)"

用于一级嵌套的方括号简写 (无需嵌套 jo 命令替换):

curl -X POST https://api.example.com/v1/orders \
    -H "Authorization: Bearer $TOKEN" \
    -d "$(jo \
        'customer[id]='"$CUSTOMER_ID" \
        'customer[name]='"$CUSTOMER_NAME" \
        'items[]='"$SKU_A" \
        'items[]='"$SKU_B")"

嵌套深度超过一级 — 通过命令替换构建 (或存入变量):

payload=$(jo \
    name="$NAME" \
    address="$(jo street="$STREET" city="$CITY")" \
    tags="$(jo -a admin user)")

curl -X POST -d "$payload" https://api.example.com/v1/users

kubectl 补丁:

kubectl patch deployment web \
    --type=merge \
    --patch "$(jo spec="$(jo replicas=3)")"

必须保持为字符串的数字 ID (否则 jo 会将 "id":12345 输出为数字):

curl -X POST -d "$(jo -- -s id=12345 name="$NAME")" \
    https://api.example.com/v1/users

修改现有的 JSON 文档:

curl -sSL https://api.example.com/v1/config \
    | jo -f - updated_at="$(date -Iseconds)" version="$NEW_VERSION"

不应使用 jo 的情况

大型固定 JSON 文档

与一长串 jo 调用相比,使用包含 JSON 字面量的 heredoc 更清晰, 而且可以直接从 API 文档复制 JSON,无需转换:

curl -X POST -d @- https://api.example.com/v1/config <<'JSON'
{
  "feature_flags": {
    "alpha": true,
    "beta": false
  },
  "limits": {
    "rps": 100,
    "burst": 200
  }
}
JSON
主机上没有 jo

某些精简的 CI 镜像或受限服务器没有安装它。 请改用 heredoc; 不要退而使用脆弱的行内带引号 JSON。

安装 jo

  • macOS:brew install jo 或 sudo port install jo
  • Debian/Ubuntu:apt install jo
  • Fedora:dnf install jo
  • Alpine:apk add jo
  • Gentoo:emerge jo
  • Arch:pacman -S jo(位于 extra)
  • Snap:snap install jo
  • Windows:scoop install jo
  • Docker:docker run --rm jpmens/jo ...
  • 从源代码安装:https://github.com/jpmens/jo

jo 不在 aqua/mise 默认的短名称注册表中; 在由 mise 管理的主机上,请通过包管理器安装, 或使用 ubi:jpmens/jo。

适用范围

适用于任何通过 shell 代码片段输出 JSON 的场景:

  • Bash 工具调用。
  • SKILL.md / README.md / 文档中的代码片段。
  • scripts/ 下的脚本。
  • Makefile 配方。
  • CI 配置。
  • API 冒烟测试说明。

如果你在编辑文件时发现手写的行内 JSON 字符串, 请在同一次编辑中将其替换为等效的 jo 写法。

评论

支持 Markdown