2016-12-09 3 views
1

Ich erstelle eine PSObject aus einer JSON-DateiPowershell erstellen Objekt aus mehreren Dateien

bar.json

{ 
    "derp": { 
    "buzz": 42 
    }, 
    "woot": { 
    "toot": 9000 
    } 
} 

ich ein PSCustomObject die json machen

$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json 
$foo.gettype() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  False PSCustomObject       System.Object 
mit ConvertFrom-Json bilden

Wenn ich jedoch mehrere JSON-Dateien versuche und splat, bekomme ich ein Array

$foo = Get-Content .\*.json -Raw |ConvertFrom-Json 
$foo.gettype() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  False Object[]         System.Array 

Um über $ foo zu iterieren, brauche ich je nach Objekttyp 2 verschiedene Codepfade.

Kann ich ein einzelnes Objekt aus mehreren JSON-Dateien abrufen?
Wenn nicht, wie würde ich ein Array von Objekten in ein einzelnes Objekt komprimieren?

Ich habe versucht, ein neues Objekt zu machen $bar, dass das Array alle Elemente von $foo

$bar = new-object psobject 
$bar | add-member -name $foo[0].psobject.properties.name -value $foo[0].'derp' -memberType NoteProperty 

aktualisieren
Per Walter Mitty Antrag enthält. Wenn ich eine einzelne Datei laden und $foo[0]

$foo = Get-Content .\bar.json -Raw |ConvertFrom-Json 
$foo[0].gettype() 

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

$foo[0] 

derp             woot 
------------           ------------ 
@{Provisioners=System.Object[]; OS=windows; Size=; V... @{Provisioners=System.Object[]; OS=windows; Size=; V... 

Lösung

ich anfangs AP Antwort implementiert laufen, aber später Refactoring es mklement0 Antwort zu verwenden.

Während $ allObjects ein Array ist, erlaubt es mir noch mit Namen Werte zu verweisen, das ist, was ich für

$allObjects = @(
    Get-ChildItem '.\foo' -Filter *.json -Recurse | Get-Content -Raw | ConvertFrom-Json 
) 

# iterating over nested objects inside an array is hard. 
# make it easier by moving all array objects into 1 parent object where 
# the 'key' is the name (opposed to AP's answer where filename = key) 
$newObject = New-Object PSObject 
foreach ($i in $allObjects) { 
    $i.psobject.members | ?{$_.Membertype -eq 'noteproperty'} |%{$newObject | add-member $_.Name $_.Value} 
} 
+0

Was möchten Sie passieren erwarten, wenn zwei json Dateien/Objekten die gleiche Eigenschaft mit unterschiedlichen Werten haben? –

+0

Guter Punkt, würde ich einen Fehler erwarten, wenn ein Schlüssel nicht eindeutig ist – spuder

+3

Ich könnte falsch liegen, aber ich denke, ein Array von Objekten ist ein Objekt. –

Antwort

2

suchen Wenn alles, was Sie ein Array von JSON-Objekte wollen, die sich aus der unterschiedlichen analysiert werden Dateien:

$final = @{} 

# Loop Thru All JSON Files, and add to $Final[<name>] = <JSON> 
ls .\*.json | % { 
    $o = cat $_ -Raw | ConvertFrom-Json 
    $final[$_.name] = [PsCustomObject]$o 
} 
$final = [PsCustomObject]$final 

hier einen Namen produzieren -> Datenkarte für alle Ihre JSON-Dateien als verschachtelte PSObject

+0

In der Linux-Welt wird das Parsen der Ausgabe von "ls" abgeraten. Ist Windows gleich? – spuder

+1

Nichts in PowerShell gibt tatsächlich nur Strings zurück, sie sind Objekte mit Feldern. –

+0

@spuder ls und cat in powershell sind nur Alias ​​für 'get-childitem' und' get-content' @AP. Ich bekomme diesen Fehler mit Ihrem Code 'Der Splatting-Operator '@' kann nicht verwendet werden, um Variablen in einem Ausdruck zu referenzieren.' – LotPings

1

AP.'s helpful answer ist eine elegante Lösung, die für die Schaffung eines einzigen Objekt der obersten Ebene ([pscustomobject] Beispiel):

  • beherbergt alle JSON gewandelten Objekte als Eigenschaften für ihre Eingangs genannten Dateinamen.

    • Z.B. $final würde das Objekt Äquivalent der JSON Zeichenfolge von der Frage eine bar.json Eigenschaft, deren Wert enthalten ist.

    • Ein Vorbehalt ist, dass mit doppelten Dateinamen die zuletzt bearbeitete Datei "gewinnen" würde.

Boden für eine Nutzung zur Kenntnis re Unix-Aliasnamen ls und cat ansehen.


Um erhalten eine Array aller konvertiert-from-JSON-Objekte, die folgende genügt:

$allObjects = @(Get-ChildItem -Filter *.json | Get-Content -Raw | ConvertFrom-Json) 

Beachten Sie, dass, wenn Sie benötigen einen einzigen Verzeichnis des JSON Dateien,
$allObjects = @(Get-Content -Path *.json -Raw | ConvertFrom-Json) funktioniert auch.

Notiere die Verwendung von @(...) die Array subexpression Operator, der gewährleistet, dass das zurückgeführt wird als Array behandelt wird, auch wenn nur ein einzelnes Objekt zurückgegeben wird.

  • standardmäßig oder wenn Sie $(...) verwenden, die regelmäßige subexpression Operator, auspackt Powershell jede (möglicherweise verschachtelte) Einzelteil-Kollektion und gibt nur das Einzelteil selbst; siehe Get-Help about_Operators.

Ein Hinweis auf die Verwendung von Unix-Aliasnamen ls und cat für Get-ChildItem der Powershell und Get-Content Cmdlets jeweils:

  • Nun, da Powershell Cross-Plattform ist, diese Aliase existiert nur in der Windows Ausgabe von PowerShell, während eine Entscheidung getroffen wurde, sie von PowerShell Core auf Unix-Plattformen wegzulassen, so nicht Schatten der Standard-Unix-Utilities mit dem gleichen Namen.

  • Es ist besser in die Gewohnheit, von eigenen Aliase der Powershell mit, den vorgeschriebenen Benennungskonventionen folgen und mit plattformspezifischen Dienstprogramme nicht in Konflikt geraten.

    • Z. B. gci für Get-ChildItem und gc für Get-Content
    • Für die Namenskonventionen hinter Powershell eigenen Aliasnamen verwendet werden, finden Sie in der documentation.
Verwandte Themen