You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用jq验证符合Shell变量命名等规则的JSON文件?

使用JQ验证JSON并转换为Bash兼容格式

问题

我正在编写一个bash库,需要读取包含用户输入的JSON文件;该JSON不会被篡改,但可能包含对bash脚本有害的值,具体取决于上游表单的验证情况。

在将JSON加载到bash数组的函数中,我尚不清楚必须存在哪些键,但仍需强制执行以下规则:

  • JSON必须包含单个对象
  • 所有键需符合Shell变量命名规范
  • 所有值必须是标量
  • 值中不能包含NUL字节

示例JSON

错误示例

{
  "": "empty key shall fail",
  "illegal key shall fail": "keys shall follow the naming convention of shell variables",
  "non_scalar_shall_fail_1": [1,2],
  "non_scalar_shall_fail_2": {"k":"v"},
  "nul_byte_shall_fail": "file.php\u0000.txt"
}

合法示例

{
  "task_uuid": "5d7ea654-b649-452b-a8fd-002b56be9a59",
  "task_name": "hello world",
  "user_email": null,
  "min": 7,
  "max": 100,
  "ave": 2.5,
  "file_in": "data.txt",
  "file_out": "results.txt"
}

现有脚本与问题

我已能强制执行部分规则,但不知道如何实现单个对象验证和标量值验证,现有jq脚本如下:

jq -r '
    to_entries[] |
    if (.key | test("\\A[_a-zA-Z]\\w*\\z") | not)
    then
        ("error: illegal key " + (.key | tojson) + "\n" |
        halt_error(1))
    else
        if (.value | tostring | test("\u0000"))
        then
            ("error: NUL byte in value " + (.value | tojson) + "\n" |
            halt_error(1))
        else
            # dummy output
            .key + "=" + (.value | @sh)
        end
    end
'

执行后出现异常:halt_error仅拦截部分错误,还触发了核心转储:

error: illegal key ""
task_uuid='5d7ea654-b649-452b-a8fd-002b56be9a59'
task_name='hello world'
user_email=null
min=7
max=100
ave=2.5
file_in='data.txt'
file_out='results.txt'
*** Error in `jq': corrupted double-linked list ***
...
Aborted                 (core dumped)

请问是否可以用jq完成所有这些验证,还是需要更换其他工具?

解决方法

完全可以用jq完成所有规则验证,核心转储是因为遍历逻辑导致jq在触发错误后仍继续处理后续输入,损坏了内部状态。以下是覆盖所有规则的修复脚本:

完整验证脚本

jq -r '
    # 验证规则1:输入必须是单个JSON对象
    if type != "object" then
        ("error: input must be a single JSON object\n" | halt_error(1))
    end

    # 遍历键值对,验证剩余规则并输出结果
    | to_entries[]
    | (
        # 验证规则2:键符合Shell变量命名规范
        if .key | test("\\A[_a-zA-Z]\\w*\\z") | not then
            ("error: illegal key " + (.key | tojson) + "\n" | halt_error(1))
        end

        # 验证规则3:值为标量类型(null/布尔/数字/字符串)
        | if .value | type | IN("null", "boolean", "number", "string") | not then
            ("error: non-scalar value for key " + (.key | tojson) + "\n" | halt_error(1))
        end

        # 验证规则4:字符串值不含NUL字节(其他标量无需检查)
        | if .value | type == "string" and (.value | test("\u0000")) then
            ("error: NUL byte in value for key " + (.key | tojson) + "\n" | halt_error(1))
        end

        # 输出bash兼容的键值对格式
        | .key + "=" + (.value | @sh)
    )
'

关键改进说明

  1. 规则1实现:首先检查输入类型是否为object,直接拦截数组、多个对象、原始值等非法输入。
  2. 规则3实现:通过type | IN(...)判断值是否为标量,数组和对象类型会被立即报错终止。
  3. 修复核心转储:将所有逻辑整合到单个管道中,确保halt_error触发后立即终止整个jq进程,不会继续处理后续输入条目或对象。
  4. 性能优化:仅对字符串类型检查NUL字节,其他标量类型无NUL风险,无需额外检查。

使用方式

  • 将脚本内联到bash函数或保存为独立文件
  • 执行验证:jq -r '<脚本内容>' input.json
  • 验证通过时输出可直接导入bash的键值对,例如:source <(jq -r '<脚本内容>' input.json)
  • 验证失败时输出错误信息并返回非零退出码,可被bash脚本捕获判断

内容的提问来源于stack exchange,提问作者Fravadona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:14:54