PowerShell 调用 curl.exe 发送 JSON 时双引号丢失
PowerShell 中用 curl.exe 发送内联 JSON,接口却收到缺少双引号的内容。说明旧式本机参数传递的影响、PowerShell 7.3 的行为边界,以及通过 JSON 文件发送和核对原始请求体的方法。
在 Windows PowerShell 或使用旧式参数传递的 PowerShell 中,把 JSON 放进单引号字符串后交给 curl.exe,接口仍可能收到缺少双引号的请求体。比如下面这条命令,输入看起来是合法 JSON,服务端却可能把字段名视为无引号文本,报 JSON 解析错误:
curl.exe --header 'Content-Type: application/json' --data-raw '{"name":"demo"}' 'https://api.example.com/test-json'
这里的地址是占位值。排查时换成自己控制、不会产生真实业务变更的测试接口,只发送不含凭据的样本。
如果相同内容从文件发送后正常,而内联字符串里的双引号消失,应检查 PowerShell 向本机程序传参的方式。单引号保证字符串在 PowerShell 内按字面解释,却不能保证旧式本机参数传递会保留其中的双引号。给请求补上 JSON 请求头,也不会修复已经变化的请求体。
确认当前会话的版本和参数模式
在运行脚本的 PowerShell 会话里查看版本:
$PSVersionTable.PSVersion
curl.exe --version
这两个版本分别属于 shell 和 curl。仅更新 curl,不能代替检查 shell 的传参行为;终端窗口的外观也不能说明当前启动的是哪个 PowerShell。
PowerShell 7.3 改变了本机程序的参数传递方式。新模式会保留字符串中嵌入的引号;Windows 上默认采用 Windows 模式。Windows PowerShell 5.1 的旧行为,以及显式选择的 Legacy 模式,需要分开处理。
若当前版本为 PowerShell 7.3 或更新版本,再查看:
$PSNativeCommandArgumentPassing
直接调用 curl.exe 时,Windows 和 Standard 模式可保留上述 JSON 字符串中的双引号;Legacy 使用历史行为。不要只凭“版本已经超过 7.3”就排除这个问题,脚本或会话配置仍可能选择旧模式。
这条判断针对直接调用可执行文件。如果命令还经过 cmd.exe、批处理文件或其他包装脚本,应继续检查中间那层如何拼接参数。Windows 模式对部分程序和脚本类型会回退到旧行为,不能把直接调用 curl 的结果推广到所有调用链。
用文件发送,避开 JSON 在命令行中的转义
需要兼容旧环境,或暂时不准备调整 PowerShell 时,可以让 curl 自己打开 JSON 文件。用编辑器把以下内容保存为当前工作目录下的 payload.json,选择 UTF-8、无 BOM 编码:
{"name":"demo"}
然后在 PowerShell 中发送:
curl.exe --header 'Content-Type: application/json' --data-binary '@payload.json' 'https://api.example.com/test-json'
此时 shell 只传递文件名,JSON 内部的双引号不再经过命令行参数转换。--data-binary 读取文件并保留其内容,包括换行;请求头明确告诉接口按 JSON 处理。它不会自动验证 JSON 语法,也不会修正文件本身的编码或内容。
@payload.json 外侧的单引号属于 PowerShell 语法,不应写入文件。文件不在当前目录时,将这个参数换成实际路径,例如 '@C:\work\payload.json';路径也可以包含空格,但整个参数仍需作为一个字符串传入。
不要沿用 --data-raw '@payload.json'。--data-raw 不解释开头的 @,会把文件名标记当作请求体发送,服务端自然收不到文件里的 JSON。
如果文件发送正确、内联发送缺少引号,重点就在参数传递;如果两者都失败,则继续检查原始请求体、文件内容、媒体类型和接口要求,不应直接认定是同一个原因。
新版 PowerShell 下恢复内联写法
在受支持的新版 PowerShell 会话中,确认参数模式是 Windows 或 Standard,并直接调用 curl.exe 后,可以使用开头的内联命令。这里的 7.3 是行为变化的版本边界,不表示应专门安装这个旧版本。
若现有环境必须保留 Legacy,继续用文件方案通常更容易维护。不要为了这一条请求就修改所有会话的默认参数模式:既有脚本可能已经为旧行为添加了额外转义,新模式下反而会传出多余字符。确需迁移时,应保留旧脚本与配置,在测试环境逐项核对本机程序实际收到的参数。
把 JSON 先赋给变量或改成多行字符串,只改变了 PowerShell 内字符串的构造方式;最终仍要把字符串交给本机程序,不能据此证明引号会完整到达 curl。也不要把 Bash、CMD 和 PowerShell 的转义字符混在同一条命令里不断叠加。
以接口收到的内容验收
先用上面的无敏感信息样本,在测试服务端检查未经格式化的原始请求体,确认字段名和值两侧的双引号存在;再确认 JSON 解析成功,得到的 name 字段值为 demo。如果日志只显示解析后的对象,日志格式本身可能省略引号,不能仅凭这种显示认定发送内容有误。
curl 正常结束或返回了 HTTP 响应,都不足以证明业务接口接受了 JSON。还应检查响应状态、响应内容和服务端处理结果。已发出的 POST 可能产生业务变更;重试前先确认前一次请求是否已处理,避免重复提交。
排查完成后,按本地数据管理要求清理测试文件。若从内联改为文件发送,保留原命令即可撤回这项调整;撤回命令不能撤销服务端已经完成的操作。用于正式请求的 JSON 文件若含有敏感数据,应限制文件访问并避免提交到代码仓库。


