代码之家  ›  专栏  ›  技术社区  ›  Gregory Suvalian

如何在ConvertTo-Json cmdlet中将枚举保留为“Strings”?[副本]

  •  2
  • Gregory Suvalian  · 技术社区  · 6 年前

    获取Msoldomain 我们称之为输出1 )其中Name、Status和Authentication是属性名,下面是它们各自的值。

    Name                    Status   Authentication
    
    myemail.onmicrosoft.com Verified Managed
    

    GetMsolDomain |ConvertTo-Json
    

    我得到下面的输出( 我们称之为输出 )Json格式。

    {
        "ExtensionData":  {
    
                          },
        "Authentication":  0,
        "Capabilities":  5,
        "IsDefault":  true,
        "IsInitial":  true,
        "Name":  "myemail.onmicrosoft.com",
        "RootDomain":  null,
        "Status":  1,
        "VerificationMethod":  1
    }
    

    但是,问题是,如果你注意到 地位 验证方法 财产。不使用ConvertTo JSon Powershell就给出文本,使用converttojson就给出整数。

    当我发出以下命令时

    get-msoldomain |Select-object @{Name='Status';Expression={"$($_.Status)"}}|ConvertTo-json
    

    {
        "Status":  "Verified"
    }
    

    但是,我想要一些东西,这样我就不必指定任何特定的属性名来转换它,就像我在上面指定的那样

    Select-object @{Name='Status';Expression={"$($_.Status)"}}
    

    地位 财产而不是 验证方法 属性,因为这是我作为输入提供的。

    问:有什么通用的东西我可以给 “司令官,让它回来 枚举属性是文本而不是整数,没有显式命名它们,因此我得到如下输出:

    {
        "ExtensionData":  {
    
                          },
        "Authentication":  0,
        "Capabilities":  5,
        "IsDefault":  true,
        "IsInitial":  true,
        "Name":  "myemail.onmicrosoft.com",
        "RootDomain":  null,
        "Status":  "Verified",
        "VerificationMethod":  "DnsRecord"
    }
    
    0 回复  |  直到 7 年前
        1
  •  6
  •   Avshalom    6 年前

    好吧,如果您不介意花点时间:)您可以将它转换为CSV,这将强制字符串输出,然后将它从CSV重新转换回PS对象,最后再转换回Json。

    这样地:

    Get-MsolDomain | ConvertTo-Csv | ConvertFrom-Csv | ConvertTo-Json
    
    • 如果需要保留原始类型而不是将其全部转换为字符串,请参阅mklement0帮助解答。。。
        2
  •  5
  •   mklement0    5 年前

    核心 ConvertTo-Json -EnumsAsStrings 转换

    GetMsolDomain | ConvertTo-Json -EnumsAsStrings  # PS *Core* only
    

    不幸的是,这个开关 中不支持 Windows PowerShell .

    Avshalom's answer 全部 属性值总是转换为 在这个过程中,这通常是不可取的(例如 Authentication 数字 0 会变成 一串 '0'

    这里有一个更通用的 它递归地内省输入对象并输出有序的哈希表,这些哈希表反映了枚举值转换为字符串和传递的所有其他值的输入属性,然后可以传递给 :

    Filter ConvertTo-EnumsAsStrings ([int] $Depth = 2, [int] $CurrDepth = 0) {
      if ($_ -is [enum]) { # enum value -> convert to symbolic name as string
        $_.ToString() 
      } elseif ($null -eq $_ -or $_.GetType().IsPrimitive -or $_ -is [string] -or $_ -is [decimal] -or $_ -is [datetime] -or $_ -is [datetimeoffset]) {
        $_
      } elseif ($_ -is [Collections.IEnumerable]) {
        , ($_ | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1))
      } else { # non-primitive type -> recurse on properties
        if ($CurrDepth -gt $Depth) { # depth exceeded -> return .ToString() representation
          "$_"
        } else {
          $oht = [ordered] @{}
          foreach ($prop in $_.psobject.properties) {
            if ($prop.Value -is [Collections.IEnumerable] -and -not $prop.Value -is [string]) {
              $oht[$prop.Name] = @($prop.Value | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1))
            } else {      
              $oht[$prop.Name] = $prop.Value | ConvertTo-EnumsAsStrings -Depth $Depth -CurrDepth ($CurrDepth+1)
            }
          }
          $oht
        }
      }
    }
    

    转换为Json ,递归深度( -Depth 2 默认情况下,为了防止无限递归/过大的输出(就像您在使用诸如 [System.IO.FileInfo] Get-ChildItem ,例如)。类似地,超过隐含深度或指定深度的值由 .ToString() 显式地控制递归深度。

    PS> [pscustomobject] @{ p1 = [platformId]::Unix; p2 = 'hi'; p3 = 1; p4 = $true } | 
          ConvertTo-EnumsAsStrings -Depth 2 |
            ConvertTo-Json
    
    {
      "p1": "Unix",   # Enum value [platformId]::Unix represented as string.
      "p2": "hi",     # Other types of values were left as-is.
      "p3": 1,
      "p4": true
    }
    

    注: -Depth 2 在这里没有必要 2个 ),但这里显示的是提醒您可能希望显式控制它。

    推荐文章