PowerShell 的 Format-List 和 ConvertTo-Json 之间的序列化差异

Serialization differences between PowerShell's Format-List and ConvertTo-Json

我正在尝试在 Python 中解析 PowerShell Get-NetIPConfiguration 的结果。

结果包含我想要的默认格式(格式列表)的值,但在转换为 JSON 时不包含,这是我想要使用的格式。

注意 DNSServer 是如何被 Format-List 序列化的:

PS C:\Users\BoppreH> Get-NetIPConfiguration | Format-List
InterfaceAlias       : VirtualBox Host-Only Network
InterfaceIndex       : 23
InterfaceDescription : VirtualBox Host-Only Ethernet Adapter
IPv4Address          : 192.168.56.1
IPv6DefaultGateway   :
IPv4DefaultGateway   :
DNSServer            : fec0:0:0:ffff::1
                       fec0:0:0:ffff::2
                       fec0:0:0:ffff::3

[...]

ConvertTo-Json -Depth 1 以不同方式序列化 DNSServer 属性(以完全无用的方式):

PS C:\Users\BoppreH> Get-NetIPConfiguration | ConvertTo-Json -Depth 1
[
    {
        "Detailed":  false,
        "ComputerName":  "BOPPREH-DESKTOP",
        "InterfaceAlias":  "VirtualBox Host-Only Network",
        "InterfaceIndex":  23,
        "InterfaceDescription":  "VirtualBox Host-Only Ethernet Adapter",
        "CompartmentId":  1,
        "NetAdapter":  "MSFT_NetAdapter (CreationClassName = \"MSFT_NetAdapter\", DeviceID = \"{EAF79493-7C78-44D2-ADB4-F3EF196D2F49}\", SystemCreationClassName = \"CIM_NetworkPort\", SystemName = \"boppreh-desktop\")",
        "NetCompartment":  "MSFT_NetCompartment (InstanceID = \";55;\")",
        "NetIPv6Interface":  "MSFT_NetIPInterface (Name = \"??55??55;\", CreationClassName = \"\", SystemCreationClassName = \"\", SystemName = \"\")",
        "NetIPv4Interface":  "MSFT_NetIPInterface (Name = \"??55?55;\", CreationClassName = \"\", SystemCreationClassName = \"\", SystemName = \"\")",
        "NetProfile":  null,
        "AllIPAddresses":  "192.168.56.1 fe80::d83f:9609:86ff:2b57%23",
        "IPv6Address":  "",
        "IPv6TemporaryAddress":  "",
        "IPv6LinkLocalAddress":  "fe80::d83f:9609:86ff:2b57%23",
        "IPv4Address":  "192.168.56.1",
        "IPv6DefaultGateway":  null,
        "IPv4DefaultGateway":  null,
        "DNSServer":  "MSFT_DNSClientServerAddress (Name = \"23\", CreationClassName = \"\", SystemCreationClassName = \"\", SystemName = \"23\") MSFT_DNSClientServerAddress (Name = \"23\", CreationClassName = \"\", SystemCreationClassName = \"\", SystemName = \"2\")"
    },
[...]

直到深度级别 4 地址才可见,但到那时输出会大几倍并且更难导航。

我目前的替代方法是将结果通过管道传输到 Select-Object 并使用计算属性自行转换值(在 DNSServer 的情况下是 $_.DNSServer.ServerAddresses -join " "),但这对每个人来说都很麻烦属性 并使其他属性也以不同方式序列化。

如何强制 JSON 序列化程序像列表格式化程序一样格式化值?

Note how DNSServer is serialized by Format-List

Format-*cmdlet 不序列化,它们使用 PowerShell 的output-formatting system (as opposed to its 生成用于显示的字符串表示 ]).

这些表示 不是 用于 程序化处理 ,但如果您确实想将它们处理为 strings,你可以将它们传送到 Out-String:

# Returns a single-line string; add -Stream to get an array of lines.
# Add -Width to explicitly specify a line width (console window width is the default).
# Note: Since Format-List is used for formatting *by default*, 
#       you don't strictly need the Format-List here.
#       Alternatively, use Format-Table for a *table* representation
$stringRep = Get-NetIPConfiguration | Format-List | Out-String

How can I force the JSON serializer to format values like the list formatter?

您唯一的选择确实是通过构建您自己的 [pscustomobject] 实例来简化对象图,例如通过 Select-Object and calculated properties, or in a ForEach-Object 循环 [pscustomobject] 文字 (例如
[pscustomobject] @{ foo = 'bar'; baz = 'quux' }).

例如:

Get-NetIPConfiguration | ForEach-Object {
  [pscustomobject] @{
    InterfaceAlias = $_.InterfaceAlias
    InterfaceIndex = $_.InterfaceIndex
    InterfaceDescription = $_.InterfaceDescription
    'NetProfile.Name' = $_.NetProfile.Name
    IPv4Address = $_.IPv4Address -join "`n"
    IPv6DefaultGateway = $_.IPv6DefaultGateway.NextHop
    IPv4DefaultGateway = $_.IPv4DefaultGateway.NextHop
  }
}

将以上内容通过管道传输到 ConvertTo-Json 给出了合理的表示。

请注意,Get-NetIPConfigurationformatting data 具有额外的内置逻辑,可以根据适配器类型 改变其显示表示中的输出字段 ,以上没有考虑到。