Powershell - 使用ConvertTo-Json

时间:2017-06-13 08:37:37

标签: json powershell csv enums

Powershell命令 - 让 ConvertTo-Json 具有以下限制 1)它将Enum值作为整数而不是文本返回 2)它不以可读格式返回日期

对于第1点,请参见下面的Status and VerificationMethod Properties

PS C:\Windows\system32> Get-Msoldomain | ConvertTo-Json


{
    "ExtensionData":  {

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

为了解决这个问题,我改变了我的命令,如下所示

PS C:\Windows\system32> Get-Msoldomain | ConvertTo-Csv | ConvertFrom-Csv | ConvertTo-Json

{
    "ExtensionData":  "System.Runtime.Serialization.ExtensionDataObject",
    "Authentication":  "Managed",
    "Capabilities":  "Email, OfficeCommunicationsOnline",
    "IsDefault":  "True",
    "IsInitial":  "True",
    "Name":  "curtisjmspartnerhotmail.onmicrosoft.com",
    "RootDomain":  "",
    "Status":  "Verified",
    "VerificationMethod":  "DnsRecord"
}

现在您看到,返回的枚举的文本值高于(Status和VerificationMethod)而不是整数值。

但是,这种方法有一些限制:

  

1)ConvertTo-Csv不保留数组或复杂对象,和   将它们作为类名输出(观察ExtensionData属性   在两个输出中)。在第二个输出中,我们倾向于丢失数据,   并获取className    System.Runtime.Serialization.ExtensionDataObject 作为字符串

     

2)ConvertTo-Csv和ConvertFrom-Csv都不是脚本级别   命令行,但它们是命令级的命令行开关,这意味着   我们不能在脚本的末尾使用它们,但它们必须是   与我上面所做的各个命令一起使用。鉴于,   ConvertTo-Json不需要在commmandLevel中应用,只是   为脚本输出应用一次。

我的问题是:

1)我如何仍然使用convertTo-Json,以便我的所有枚举属性都返回其文本而不是整数,并且复杂对象或数组也不会丢失?在我使用的方法中,复杂的对象迷失了

2)此外,它应该是通用的,以便它可以应用于脚本的末尾,而不是在命令级别

3 个答案:

答案 0 :(得分:2)

ConvertTo-JsonConvertTo-Csv都是在某种文本表示中序列化对象的形式,并且在不同的用例中都很有用。

ConvertTo-Csv可能最适合用于表格(如电子表格)中表达的二维数据。因此,尝试将“复杂”对象(即具有包含其他结构化数据的属性的对象)转换为简单表格是很尴尬的。在这种情况下,PowerShell将此类数据表示为数据类型的全名。

ConvertTo-Json能够序列化更复杂的对象,因为格式允许嵌套的数组/数据结构,例如,示例中的 ExtensionData 属性。请注意,您可能需要使用-Depth参数来确保正确序列化深层嵌套数据。

所以问题实际上归结为ConvertTo-Json cmdlet序列化枚举的方式,可以通过以下方式演示:

[PS]> (Get-Date).DayOfWeek
Tuesday

[PS]> (Get-Date).DayOfWeek.GetType()

IsPublic IsSerial Name      BaseType   
-------- -------- ----      --------   
True     True     DayOfWeek System.Enum

[PS]> Get-Date | Select DayOfWeek | ConvertTo-Json
{
    "DayOfWeek":  2
}

因此,在转换为JSON之前,您需要确保 DayOfWeek 属性(在此示例中)或状态 VerificationMethod 属性(来自你的例子)首先转换为它们的字符串等价物。

您可以使用带有Select-Object的表达式来执行此操作,以便在数据传递到管道时进行转换。请注意,您执行需要包含所有要包含在最终JSON中的属性:

[PS]> Get-Date |
  Select DateTime,@{Label="DayOfWeek";Expression={$_.DayOfWeek.ToString()}} |
  ConvertTo-Json
{
    "DateTime":  "13 June 2017 10:33:51",
    "DayOfWeek":  "Tuesday"
}

所以在你的情况下,你需要这样的东西:

[PS]> Get-Msoldomain |
  Select-Object ExtensionData,IsDefault,IsInitial,Name,RootDomain `
    ,{Label="Authentication";Expression={$_.Authentication.ToString()}} `
    ,{Label="Capabilities";Expression={$_.Capabilities.ToString()}} `
    ,{Label="Status";Expression={$_.Status.ToString()}} `
    ,{Label="VerificationMethod";Expression={$_.VerificationMethod.ToString()}} |
  ConvertTo-Json

答案 1 :(得分:2)

@puneet,在您对我的其他答案发表评论之后,以下是一个示例,说明如何基于现有对象构建新对象,并将枚举类型转换为字符串。< / p>

我们的想法是创建一个新的“空”对象,然后循环遍历原始对象的所有属性并将它们添加到新对象中,但如果任何原始属性是Enums,那么这些属性将转换为字符串。

$data = [PSCustomObject]@{}

(Get-Date).PSObject.Properties | Select Name,Value | Foreach-Object {
  if($_.Value.GetType().BaseType.FullName -eq "System.Enum"){
    $data | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value.ToString()
  }
  else {
    $data | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value
  }
}

$data | ConvertTo-Json

您可能希望对自己的应用程序稍微有点精确,但希望它背后的想法很清楚。绝对检查JSON输出中是否正确处理了所有属性。

答案 2 :(得分:0)

在将psObject转换为json时保留枚举,数组和日期,可以使用newtonsoft。这里使用Nerdy Mishka powershell模块https://github.com/chavers/powershell-newtonsoft进行示例。

$obj = New-Object pscustomobject -Property @{Enum = (Get-DAte).DayOfWeek; int = 2; string = "du text"; array = @("un", "deux", "trois"); obj= @{enum = (Get-DAte).DayOfWeek; int = 2; string = "du text"; array = @("un", "deux", "trois")}}
Import-Module Fmg-PrettyJson
$settings = Get-NewtonsoftJsonSettings
$enumconv = "Newtonsoft.Json.Converters.StringEnumConverter"
$e = New-Object $enumconv
$settings.Converters.Add($e)
Set-NewtonsoftJsonSettings $settings
$obj | ConvertTo-NewtonsoftJson

返回:

{
  "array": [
    "un",
    "deux",
    "trois"
  ],
  "enum": "Thursday",
  "int": 2,
  "obj": {
    "enum": "Thursday",
    "array": [
      "un",
      "deux",
      "trois"
    ],
    "int": 2,
    "string": "du text"
  },
  "string": "du text"
}