为什么在PowerShell中此字符串未序列化为简单的JSON字符串

时间:2019-04-25 17:24:33

标签: json powershell

请参见下面的$a$s都是包含文本"String"的字符串,但是每个字符串都使用ConvertTo-JSON进行序列化的方式不同。

为什么$s | ConvertToJson不产生"String"

PS W:\PowerShell\powowshell> $a="String"
PS W:\PowerShell\powowshell> $a
String
PS W:\PowerShell\powowshell> $a.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS W:\PowerShell\powowshell> $a | ConvertTo-Json
"String"


PS W:\PowerShell\powowshell> $s
String
PS W:\PowerShell\powowshell> $s.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS W:\PowerShell\powowshell> $s | ConvertTo-Json
{
    "value":  "String",
    "required":  "true"
}

背景故事

$s是经过parameterValue检查的.ps1的{​​{1}}:

Get-Help

dosdir.ps1

PS W:\PowerShell\powowshell> $cmd = (get-help -full W:\PowerShell\powowshell\examples\components\dosdir.ps1).Syntax.syntaxItem[0].parameter
PS W:\PowerShell\powowshell> $cmd | convertto-json
{
    "description":  [
                        {
                            "Text":  "The path to the directory to be listed"
                        }
                    ],
    "parameterValue":  {
                           "value":  "String",
                           "required":  "true"
                       },
...
$s = $cmd.parameterValue

1 个答案:

答案 0 :(得分:5)

PowerShell的ETS (Extended Type System)允许您使用其他属性(只能由PowerShell代码直接访问)装饰任何对象。

如果您使用[string]实例(无论您自己完成还是使用其他命令为您执行 [1] ),这些附加属性将在对象序列化时浮出水面。与ConvertTo-Json

# Add a .foo property with value 'bar' to a string.
$decoratedString = 'hi' | Add-Member -PassThru foo bar

# Output the string as-is.
# The added property does NOT show.
$decoratedString

'---'

# Serialize the string to JSON.
# The added property DOES show and the string's actual content
# is presented as pseudo-property .value
$decoratedString | ConvertTo-Json

以上结果:

hi
---
{
  "value": "hi",
  "foo": "bar"
}

This GitHub issue讨论了这种令人惊讶的行为。

解决方法

# .psobject.BaseObject returns the underlying, undecorated object.
PS> $decoratedString.psobject.BaseObject | ConvertTo-Json
hi

[1] 正如js2010所指出的那样,检索数据的 PowerShell提供程序cmdlet -Get-ChildItemGet-Item,{ {1}},...-全部向其输出的对象添加固定数量的Get-Content成员,即NotePropertyPSPathPSParentPath,{{1} },PSChildName

因此,如果序列化使用PSDrive获得的字符串,则会遇到上述相同的问题:

PSProvider

请注意,如果是字符串,则在构造 new 字符串时,通过字符串串联或应用字符串运算符(例如{),这些额外的属性会丢失 lost 。 {1}}:

Get-Content