Linode API的Bash curl请求中变量拼接JSON引发无效JSON问题咨询
解决Linode域名更新API的JSON格式问题及空字段过滤方案
问题根源:手动拼接JSON的隐患
你遇到的「echo输出正常但curl报错」问题,本质是shell字符串解析和JSON格式要求不兼容:
- 手动拼接的JSON字符串,哪怕肉眼看起来正确,一旦变量包含空格、引号、换行等特殊字符,shell会自动拆分或转义,导致实际传给curl的JSON结构被破坏
- 直接粘贴到
-d参数能运行,是因为此时shell把整段字符串当成一个整体处理,而用变量传递时如果没正确引用,会触发shell的分词规则
正确方案:用jq动态生成合规JSON
用jq工具生成JSON是最可靠的方式,既能自动处理特殊字符转义,又能轻松实现「空字段不传递」的需求。以下是具体实现步骤:
1. 定义变量
先把需要更新的字段定义为shell变量,空值留空即可:
# 示例变量,空值的字段不会被加入JSON domain_type="" description="我的更新域名描述" master_ips="192.168.1.1,10.0.0.1" ttl_sec="3600"
2. 用jq生成过滤后的JSON
通过jq的--arg参数传递变量,再通过条件判断和过滤逻辑生成仅包含非空字段的JSON:
json_payload=$(jq -n \ --arg dt "$domain_type" \ --arg desc "$description" \ --arg ips "$master_ips" \ --arg ttl "$ttl_sec" \ ' # 初始化空对象 {} # 仅当domain_type非空时添加字段 | if $dt != "" then .domain_type = $dt else . end # 仅当description非空时添加字段 | if $desc != "" then .description = $desc else . end # 仅当master_ips非空时,拆分为数组添加 | if $ips != "" then .master_ips = ($ips | split(",")) else . end # 仅当ttl_sec非空时转为数字添加 | if $ttl != "" then .ttl_sec = ($ttl | tonumber) else . end ')
3. 调用Linode API
把生成的json_payload变量传给curl,注意用双引号包裹-d参数,确保整段JSON作为一个参数传递:
curl -X PUT \ -H "Authorization: Bearer YOUR_LINODE_API_TOKEN" \ -H "Content-Type: application/json" \ -d "$json_payload" \ https://api.linode.com/v4/domains/YOUR_DOMAIN_ID
简化写法:用with_entries批量过滤空字段
如果字段较多,可以用更简洁的方式,先定义所有可能的键值对,再过滤掉值为null的字段:
json_payload=$(jq -n \ --arg dt "$domain_type" \ --arg desc "$description" \ --arg ips "$master_ips" \ --arg ttl "$ttl_sec" \ ' { domain_type: ($dt | select(length > 0)), description: ($desc | select(length > 0)), master_ips: ($ips | select(length > 0) | split(",")), ttl_sec: ($ttl | select(length > 0) | tonumber) } # 过滤掉值为null的键值对 | with_entries(select(.value != null)) ')
关键优势
- 格式严格合规:
jq会自动处理所有特殊字符的转义(比如字符串里的双引号、换行),确保JSON符合Linode API的要求 - 空字段自动过滤:通过
select判断长度或非空,空值字段不会出现在最终的JSON中 - shell解析安全:生成的JSON变量用双引号包裹后,shell会完整传递给curl,不会触发分词或转义错误
内容的提问来源于stack exchange,提问作者Kalib Zen
相关产品推荐
相关产品推荐

