Bash字符串拼接后通过curl发送JSON至GitHub API的问题排查
问题描述
尝试通过curl调用GitHub API添加issue评论,执行的脚本如下:
body="\"\:warning\: \:exclamation\: Your pull request is not linked to any issue, please make the corresponding changes in the very first comments body by adding \'Fixes #issue-number\' or \'Resolves #issue-number\'. If your pull request isn\'t linked to any issue, ignore this comment\!\"" echo $body json="'{\"body\": ${body} }'" echo $json statusCode=`curl -X POST -H 'Accept: application/vnd.github+json' -H 'Authorization: token ****' -H 'Content-Type: application/json' https://api.github.com/repos/Ismoh/NoitaMP/issues/79/comments -d $json` echo "statusCode="$statusCode
执行echo $body输出:
"\"\:warning\: \:exclamation\: Your pull request is not linked to any issue, please make the corresponding changes in the very first comments body by adding \'Fixes #issue-number\' or \'Resolves #issue-number\'. If your pull request isn\'t linked to any issue, ignore this comment\!\""
执行echo $json输出:
'{"body": "\"\:warning\: \:exclamation\: Your pull request is not linked to any issue, please make the corresponding changes in the very first comments body by adding \'Fixes #issue-number\' or \'Resolves #issue-number\'. If your pull request isn\'t linked to any issue, ignore this comment\!\" }'
执行curl时出现错误,核心错误包括:
{ "message": "Problems parsing JSON", "documentation_url": "https://docs.github.com/rest/reference/issues#create-an-issue-comment" } curl: (6) Could not resolve host: Your ... curl: (3) unmatched close brace/bracket in URL position 1: }'
GitHub API官方示例:
curl \ -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer <YOUR-TOKEN>" \ https://api.github.com/repos/OWNER/REPO/issues/ISSUE_NUMBER/comments \ -d '{"body":"Me too"}'
疑问:操作哪里出错了?有没有更合适的JSON字符串转义方法?已尝试jq -Rsa .但无效。
错误原因
- 变量引用未加引号导致参数拆分:
-d $json没有用双引号包裹,shell会将JSON中的空格作为参数分隔符,把文本内容拆分成多个curl参数,curl错误地将这些内容当作URL处理,从而出现"无法解析主机"的错误。 - 手动JSON转义错误:手动拼接JSON时,对引号、特殊字符的转义处理混乱,生成的JSON格式不符合规范,导致GitHub API无法解析。
- 错误的JSON拼接方式:用单引号包裹整个JSON字符串,同时内部又包含转义的双引号,这种写法容易出现格式冲突,进一步破坏JSON结构。
正确解决方案
方法一:用jq自动生成JSON(推荐)
jq可以自动处理JSON所需的转义逻辑,避免手动转义的错误,写法更简洁可靠:
# 定义原始文本,无需手动转义任何字符 body=":warning: :exclamation: Your pull request is not linked to any issue, please make the corresponding changes in the very first comments body by adding 'Fixes #issue-number' or 'Resolves #issue-number'. If your pull request isn't linked to any issue, ignore this comment!" # 用jq生成符合规范的JSON,自动处理转义 json=$(jq -n --arg body "$body" '{"body": $body}') # curl调用时,必须用双引号包裹$json,防止shell拆分参数 statusCode=$(curl -X POST \ -H 'Accept: application/vnd.github+json' \ -H 'Authorization: token ****' \ -H 'Content-Type: application/json' \ https://api.github.com/repos/Ismoh/NoitaMP/issues/79/comments \ -d "$json") echo "statusCode=$statusCode"
说明:jq -n --arg body "$body" '{"body": $body}'会将shell变量$body安全传入jq,自动生成正确转义的JSON字符串,完全符合GitHub API的格式要求。
方法二:手动修正转义和变量引用(不推荐)
如果坚持手动拼接,需要严格处理引号和变量引用:
# 用单引号定义body,内部单引号通过'\''转义 body=':warning: :exclamation: Your pull request is not linked to any issue, please make the corresponding changes in the very first comments body by adding '\''Fixes #issue-number'\'' or '\''Resolves #issue-number'\''. If your pull request isn'\''t linked to any issue, ignore this comment!' # 拼接JSON,确保双引号正确转义 json="{\"body\": \"$body\"}" # curl调用时用双引号包裹$json statusCode=$(curl -X POST \ -H 'Accept: application/vnd.github+json' \ -H 'Authorization: token ****' \ -H 'Content-Type: application/json' \ https://api.github.com/repos/Ismoh/NoitaMP/issues/79/comments \ -d "$json") echo "statusCode=$statusCode"
内容的提问来源于stack exchange,提问作者Ismoh
相关产品推荐
相关产品推荐

