Powershell按字母顺序排序PSObject

时间:2017-05-18 19:52:31

标签: json powershell sorting

给定一个从json(foo.json)

创建的自定义PowerShell对象(bar)

您如何按键按字母顺序对对象进行排序?

foo.json
{
  "bbb": {"zebras": "fast"},
  "ccc": {},
  "aaa": {"apples": "good"}
}

期望的输出

foo.json
{
  "aaa": {"apples": "good"},
  "bbb": {"zebras": "fast"},
  "ccc": {}
}

实施例

$bar = get-content -raw foo.json | ConvertFrom-Json  
$bar.gettype()  

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

我使用sort-object

尝试了以下操作

$bar = $bar | Sort
$bar = $bar | Sort-Object
Sort-Object -InputObject $bar
Sort-Object -InputObject $bar -Property Name
Sort-Object -InputObject $bar -Property @{Expression="Name"}
Sort-Object -InputObject $bar -Property @{Expression={$_.PSObject.Properties.Name}}

我也尝试将PSObject转换为哈希表(哈希表似乎根据名称自动排序),然后将该哈希表转换回json,但它再次失去了顺序。

$buzz = @{}
$bar.psobject.properties |Foreach { $buzz[$_.Name] = $_.Value }
ConvertTo-Json $buzz -Depth 9

更新
更改了foo.json以包含值以及键

2 个答案:

答案 0 :(得分:4)

正如Mathias R. Jessen所述,此处没有集合排序,只有一个对象您要对其属性进行排序,因此您需要反射通过Get-Member获取对象的属性:

$bar = get-content -raw foo.json | ConvertFrom-Json

# Build an ordered hashtable of the property-value pairs.
$sortedProps = [ordered] @{}
Get-Member -Type  NoteProperty -InputObject $bar | Sort-Object Name |
  % { $sortedProps[$_.Name] = $bar.$($_.Name) }

# Create a new object that receives the sorted properties.
$barWithSortedProperties = New-Object PSCustomObject
Add-Member -InputObject $barWithSortedProperties -NotePropertyMembers $sortedProps

更简化的版本,使用-pv-PipelineVariable)来缓存" ConvertFrom-Json生成的未排序的自定义对象:

$barSortedProps = New-Object PSCustomObject
Get-Content -Raw foo.json | ConvertFrom-Json -pv jo |
  Get-Member -Type  NoteProperty | Sort-Object Name | % { 
    Add-Member -InputObject $barSortedProps -Type NoteProperty `
               -Name $_.Name -Value $jo.$($_.Name)
  }

答案 1 :(得分:0)

这个怎么样:

Function Sort-PSObject {
        [CmdletBinding()]
        Param(
            [Parameter(ValueFromPipeline=$true)]$inputString
        )
        process {
            ($inputString | out-string).trim() -split "`r`n" | sort
        }
}

可以直接从管道发送