我想做的很简单.我有一个PowerShell脚本,它应该接受JSON文本作为参数.看起来一点都不简单!

我查看了这些页面,试图了解应该如何做到这一点.about_PowerShell_exeabout_Parsingabout_Quoting_Rules.我找不到明确的解释.事实上,我看到的是与这些文件相矛盾的.命令行规则与常规规则不同.

我用的是PowerShell 5.1

我使用以下脚本进行测试:

测试PS1

param($json)
Write-Host $json

我try 传递这个JSON文本.

{"name" : "value"}

我所看到的.

powershell .\测试PS1 "{"name" : "value"}"
name : value

没有牙套.完全go 掉了双引号. 让我们试着逃脱他们.

powershell .\测试PS1 "{`"name`" : `"value`"}"
Missing closing '}' in statement block or type definition.

反勾符号并不起作用.让我们试着用双引号引起来.加倍是命令行魔术中非常流行的一种技巧.

powershell .\测试PS1 "{""name"" : ""value""}"
The string is missing the terminator: ".

让我们试着三倍的分数,因为为什么不.

powershell .\测试PS1 "{"""name""" : """value"""}"
Unexpected token ':' in expression or statement.

好的,让我们来试试单引号.

powershell .\测试PS1 '{"name" : "value"}'
{name : value}

我们有大括号,但没有双引号.让我们再一次try 逃脱他们.

powershell .\测试PS1 '{`"name`" : `"value`"}'
{`name` : `value`}

在ps有机会转义它们之前,有些东西吃掉了我们的双引号.

加倍?

powershell .\测试PS1 '{""name"" : ""value""}'
{name : value}

翻三倍?

powershell .\测试PS1 '{"""name""" : """value"""}'
{"name" : "value"}

它起作用了!多难看啊!

我想知道有没有人能很好地解释发生了什么事.我非常感谢任何文档/文章上的链接,这些链接可以解释它的实际工作原理.三个引号对我来说看起来并不太糟糕,但我的JSON参数有几层嵌套,看起来我可以在元素之前使用7个引号之类的东西结束.

-PowerShel.exe中的EncodedCommand给我一种悲伤的感觉,没有简单的解决方案.

Update.正如@mklement0所指出的,首先处理该命令行的是一个CMDshell .CMD使用双引号来处理其中包含空格的参数.它会在到达Powershell.exe之前删除成对的双引号.这意味着

  1. CMD在任何情况下都会删除第一个和最后一个引号
  2. 我们可以对所有内部引号进行CMD转义
powershell .\测试PS1 "{\"name\" : \"value\"}"
Unexpected token ':' in expression or statement.

在本例中,此字符串达到了Powershell.exe {"name" : "value"}.PowerShell已try 执行它,此代码无效.它try 执行此文本,因为默认情况下-Command是一个参数.要使其成为字符串,我们需要另一对引号,这里PowerShell的单引号非常有用.

powershell .\测试PS1 "'{\"name\" : \"value\"}'"
{"name" : "value"}

更好的解决方案是使用-File,就像@mklement0建议的那样.在这种情况下,参数不会被解释为ps代码.

powershell -File .\测试PS1 "{\"name\" : \"value\"}"

推荐答案

outside PowerShell,例如从cmd.exe/a批处理文件,使用以下内容:

powershell -File .\test.ps1 "{\"name\" : \"value\"}"

注:

  • 101 is the best way to invoke a script file via 102, the 100,因为它不会将后续参数解释为PowerShell代码(这是默认情况下发生的事情,这意味着-Command).

    • 请注意,只有"个字符.在PowerShell命令行上有syntactic个函数,在命令行解析时unescaped个函数是removed个函数.

    • 有关何时使用-File-Command的指导,请参见this answer.

  • In its CLI arguments, PowerShell requires 100 chars. that should be preserved as part of an argument / command to be escaped as 101(与PowerShell会话inside不同,它是`").

    • 注: \" works robustly on the PowerShell side, but there can be edge cases where calling from cmd.exe / a batch file requires an alternative form of escaping, namely "^"" (sic) or, with pwsh.exe, the PowerShell (Core) CLI, "" - see this answer for details.

Alternative,其中non-standard 100 JSON quoting(单引号):

正如zett42所指出的,PowerShell的ConvertFrom-Json cmdlet-在Windows PowerShell和PowerShell(从7.3.3起的核心)中-接受'...',而不是属性名称和字符串值周围的"..."(将embedded '转义为‘’then), which you can use to avoid the need for escaped"‘字符:

:: SEE CAVEAT BELOW
powershell -File .\test.ps1 "{'name' : 'value'}"

Caveat:

  • JSON标准not确实允许使用'...',因此根据谁使用JSON,not可能会起作用.

    • 值得注意的是,System.Text.Json个.NET API支持not'...'.

    • ConvertFrom-JsonConvertTo-Json的实现转移到System.Text.Json有一个plan--目前似乎被搁置了--但正如zett42指出的那样,这将构成一个重大的突破性变化,使其不太可能发生.

  • 因此,如果您知道要使用ConvertFrom-Json或其他已知支持'...'的JSON解析器,请使用'...'引号only.

  • 顺便说一句:

    • 最好不要使用other个非标准JSON特性,比如能够容忍无关紧要的尾随,、支持//个注释以及支持unquoted个属性名称(但不支持字符串值),因为已经确保了not个跨版本支持:

    • 只有基于Json.NET的PowerShell(Core)实现才支持这些非标准特性(默认情况下不变)(System.Text.Json支持 Select 性加入,但not支持'...'引号(如上所述,也不支持不带引号的属性名称).

    • 除了这syntax个差异外,还有behavioral个跨版本差异,即:

      • Select 的默认.NET整型数据类型([int](System.Int32)与[long](System.Int64)-请参见this answer.

      • .NET [datetime]实例是如何序列化和反序列化的-参见this answer.

Json相关问答推荐

两种情况下过滤的JOLT规范

如何使用PowerShell从ExchangeOnline命令执行中获得JSON输出

展平多个数组以保持顺序

如何将一个对象添加到多个对象中 JOLT

如何强制仅有一个元素的数组在JSON中生成方括号

如何使用 JOLT 将带有列表的 JSON 项目取消列出为多个项目?

Groovy JsonBuilder 在for循环中添加数组元素

使用 map_values Select 包含空格的字符串未按预期工作

JSON 字段的多个名称

解析 JSON API 响应

如何在 Node.js 中解析包含NaN的 JSON 字符串

在 JSON API Wordpress 上启用 CORS

按 JSON 数据类型 postgres 排序

规范化 JSON 文件

如何使用 Jackson 重命名 JSON 序列化中的根键

json_encode() 返回 false

Gson 将一组数据对象转换为 json - Android

使用 C# 调用 json

使用 jQuery 和 JSON 填充表单?

无法将 System.String 转换或转换为 Class 对象