见下文 $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
用 Get-Help
检查: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
dosdir.ps1 :param(
[String]$Path
)
CMD /C "DIR /B $Path"
最佳答案
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-ChildItem
, Get-Item
, Get-Content
, ... - 全部添加固定数量NoteProperty
他们输出的对象的成员,即 PSPath
, PSParentPath
, PSChildName
, PSDrive
, PSProvider
.因此,如果您序列化使用
Get-Content
获得的字符串,您将遇到上面详述的相同问题。 :PS> 'hi' > t.txt; Get-Content t.txt | ConvertTo-Json
{
"value": "hi",
"PSPath": "/Users/jdoe/t.txt",
"PSParentPath": "/Users/jdoe",
"PSChildName": "t.txt",
"PSDrive": {
"CurrentLocation": "Users/jdoe",
"Name": "/",
"Provider": {
"ImplementingType": "Microsoft.PowerShell.Commands.FileSystemProvider",
"HelpFile": "System.Management.Automation.dll-Help.xml",
"Name": "FileSystem",
"PSSnapIn": "Microsoft.PowerShell.Core",
...
请注意,在字符串的情况下,通过字符串连接或应用字符串运算符(例如 -replace
)构建新字符串时,这些额外的属性将丢失。 :# String concatenation
PS> 'hi' > t.txt; (Get-Content t.txt) + '!' | ConvertTo-Json
hi!
# Using -replace
PS> (Get-Content t.txt) -replace 'i', 'o' | ConvertTo-Json
ho
还要注意这个每个输出对象的装饰增加了相当多的内存和性能开销 ;为 Get-Content
, GitHub issue #7537建议提供选择退出。
关于json - 为什么此字符串不在 PowerShell 中序列化为简单的 JSON 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55854660/