如何在curl中处理含空格的JSON?PowerShell POST请求问题
这个问题我之前也碰到过,核心原因是PowerShell对命令行参数的解析逻辑和curl的期望不匹配——带空格的字符串很容易被PowerShell拆分成多个独立参数,导致curl收到不完整的JSON,进而提示“JSON未终止”。下面给你几个靠谱的解决方案:
方案1:用ConvertTo-Json自动生成合法JSON(推荐)
手动拼接JSON字符串很容易出错,尤其是处理带空格、特殊字符的内容时。PowerShell自带的ConvertTo-Json cmdlet可以帮你自动生成格式正确的JSON,完全避免手动拼接的问题:
# 定义参数和日期变量 $apitoken = "your-api-token-here" $interval = 7 # 示例:减7天 # 构建请求体对象 $requestBody = @{ apitoken = $apitoken startdate = (Get-Date).AddDays(-$interval).ToString("yyyy-MM-dd HH:mm:ss") enddate = Get-Date.ToString("yyyy-MM-dd HH:mm:ss") } # 转换为压缩格式的JSON(也可以去掉-Compress保留换行) $jsonBody = $requestBody | ConvertTo-Json -Compress # 调用curl,用--data-raw原封不动传递JSON curl -X POST ` -H "Content-Type: application/json" ` --data-raw $jsonBody ` "https://your-target-api-url.com"
为什么这个方法有效?
ConvertTo-Json会自动处理所有字符串的转义逻辑,包括空格、引号等特殊字符,生成的JSON完全符合语法规范。加上--data-raw参数后,curl会原封不动地接收整个JSON字符串,不会把空格当作参数分隔符。
方案2:用Here-String构建JSON字符串
如果你更习惯手动写JSON结构,可以用PowerShell的Here-String(多行字符串语法)来保留所有格式,包括空格:
$apitoken = "your-api-token-here" $interval = 7 $startDate = (Get-Date).AddDays(-$interval).ToString("yyyy-MM-dd HH:mm:ss") $endDate = Get-Date.ToString("yyyy-MM-dd HH:mm:ss") # Here-String用@"和"@包裹,内部可以直接写带空格的变量 $jsonBody = @" { "apitoken": "$apitoken", "startdate": "$startDate", "enddate": "$endDate" } "@ # 同样用--data-raw传递 curl -X POST ` -H "Content-Type: application/json" ` --data-raw $jsonBody ` "https://your-target-api-url.com"
为什么之前的单/双引号没用?
在PowerShell中,如果你直接写类似-d '{"startdate": "$startDate"}'的代码,PowerShell会先替换变量,然后把空格后的内容当作新的参数传给curl。比如$startDate的值是"2024-05-20 00:00:00",替换后整个字符串会被拆成{"startdate": "2024-05-20和00:00:00"}两个参数,curl自然会认为JSON未终止。
额外建议:用PowerShell原生的Invoke-WebRequest
如果不需要严格使用curl命令,PowerShell的Invoke-WebRequest(或Invoke-RestMethod)对PowerShell的字符串和对象支持更好,完全不需要担心参数解析问题:
$requestBody = @{ apitoken = $apitoken startdate = (Get-Date).AddDays(-$interval).ToString("yyyy-MM-dd HH:mm:ss") enddate = Get-Date.ToString("yyyy-MM-dd HH:mm:ss") } Invoke-RestMethod -Uri "https://your-target-api-url.com" ` -Method Post ` -Body ($requestBody | ConvertTo-Json) ` -ContentType "application/json"
内容的提问来源于stack exchange,提问作者kumaheiyama

