Jenkins Pipeline中curl发起POST请求时无法转义双引号内星号*的问题
问题根因
报错与星号*本身无关,核心是多层嵌套结构的双引号转义缺失:
原请求体的JSON字符串中直接写入了带双引号的XML片段,JSON解析器读到type="*"位置的第一个双引号时,会判定DOMAIN字段的字符串值已经提前结束,后续的*会被识别为JSON结构层的非法字符,最终抛出Unexpected character ('*' (code 42))的解析错误。
另外原命令中的XML片段本身存在语法残缺:<domain type="*"</未正确闭合标签,即使JSON解析通过,后续Java应用读取XML配置时也会抛出格式错误。
可行解决方案
1. 原生Shell执行Curl的修正写法
对JSON字符串内部嵌套的双引号添加反斜杠转义,同时补全XML标签闭合,修正后命令如下:
curl --location --request POST some.link/api/.../properties \ --header 'X-Corellation-Id: abcd' \ --header 'Content-Type: application/json' \ -d '{"addOrUpdate": [{ "name": "pod1" , "properties": { "DOMAIN" : "<domain type=\"*\" />" }}]}'
改动点说明:
- XML片段中
type="*"的两个双引号前均添加\做JSON层面转义,避免提前截断字符串 - 将残缺的XML片段补全为标准自闭合标签格式,消除后续XML解析隐患
2. Jenkins Pipeline(Groovy脚本)场景的稳妥写法
Groovy中嵌套Shell、JSON、XML三层结构时,手动写转义符非常容易出错,优先选择以下两种方案:
推荐方案:用Groovy内置JsonOutput自动序列化JSON
不需要手动处理任何转义逻辑,由工具自动生成合法JSON结构,从根源避免转义错误:
import groovy.json.JsonOutput // 直接构造请求体结构,XML片段中的双引号、特殊字符直接书写即可 def requestMap = [ addOrUpdate: [ [ name: "pod1", properties: [ DOMAIN: '<domain type="*" />' ] ] ] ] // 自动序列化为标准JSON字符串,所有需要转义的字符会自动处理 def jsonPayload = JsonOutput.toJson(requestMap) // 执行curl请求,用--data-binary传参避免特殊字符被额外转义 sh """ curl --location --request POST some.link/api/.../properties \ --header 'X-Corellation-Id: abcd' \ --header 'Content-Type: application/json' \ --data-binary '${jsonPayload}' """
备选方案:硬拼字符串的转义规则
如果不使用序列化工具硬拼命令,需要注意Groovy、Shell、JSON三层转义规则:JSON内部的双引号需要写3个反斜杠转义,星号本身不需要额外转义,示例:
sh 'curl --location --request POST some.link/api/.../properties --header "X-Corellation-Id: abcd" --header "Content-Type: application/json" -d \'{"addOrUpdate": [{ "name": "pod1" , "properties": { "DOMAIN" : "<domain type=\\\"*\\\" />" }}]}\''
该写法可读性极差,字段调整时极易出现转义遗漏,非必要不推荐使用。
避坑说明
- 星号
*属于JSON规范中的普通字符,本身不需要任何转义,之前的转义失败本质是双引号未转义导致字符串提前截断,把*暴露到了JSON语法结构层 - 不要在多层嵌套场景下反复尝试单双引号组合拼JSON,转义规则会随嵌套层数指数级变复杂,使用内置序列化工具是成本最低的可靠性方案
- 发送JSON请求时优先用
--data-binary代替-d参数,避免部分curl版本对特殊字符做额外的转义处理 - 生成请求体后可先打印JSON内容做格式校验,确认结构合法后再发送请求
内容的提问来源于stack exchange,提问作者Rado Ratko
相关产品推荐
相关产品推荐

