dani
Goto Top

Wie kann ich auf Werte eines JSON-Arrays zugreifen?

Guten Morgen Kolleginnen und Kollegen,
erstmal auch noch von meiner Seite eine gutes neues Jahr.

Ich versuche zur Zeit, über die RIPE Database RESTful API zu einem bestimmten AS, sämtliche IP-Subnetze auszulesen. Am Schluss sollen die Werte in eine CSV-Datei geschrieben werden, welche als Namen z.b. as3320.csv besitzt. Das ist erstmal zweitrangig...

So rufe ich die Daten ab:
$rest = Invoke-RestMethod -Uri "http://rest.db.ripe.net/search.json?query-string=AS3320&inverse-attribute=origin&type-filter=route" -ContentType application/json -Method Get  

Wenn ich danach in der Powershell foglendes "$rest.objects.object.attributes" eingebe, erhalte ich folgende Ausgabe:
attribute                                                                                                                                                                                                                                                        
---------                                                                                                                                                                                                                                                        
{@{name=route; value=103.244.56.0/23}, @{name=descr; value=part of 103.244.56.0/22}, @{name=descr; value=LENOVO (shanghai) Co.ltd}, @{name=descr; value=registered at APNIC}...}                                                                                 
{@{name=organisation; value=ORG-LCL10-RIPE}, @{name=org-name; value=Lenovo (Shanghai) Co., Ltd.}, @{name=org-type; value=OTHER}, @{name=address; value=Shanghai, China}...}                                                                                      
{@{name=route; value=109.237.176.0/20}, @{name=descr; value=T-Mobile Deutschland GmbH}, @{name=remarks; value=secure routing by AS3320 aggregate}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}...}                                              
{@{name=route; value=129.181.208.0/21}, @{name=descr; value=TENOVIS}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                                             
{@{name=route; value=129.181.216.0/22}, @{name=descr; value=BULL}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                                                
{@{name=route; value=131.176.233.0/24}, @{name=descr; value=European Space Agency (ESA)}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                         
{@{name=route; value=131.176.234.0/24}, @{name=descr; value=European Space Agency (ESA)}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                         
{@{name=route; value=131.176.235.0/24}, @{name=descr; value=European Space Agency (ESA)}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                         
{@{name=route; value=131.176.236.0/24}, @{name=descr; value=European Space Agency (ESA)}, @{link=; name=origin; value=AS3320; referenced-type=aut-num}, @{link=; name=mnt-by; value=DTAG-RR; referenced-type=mntner}...}                                         
...
Ich habe das Ergebnis etwas gekürzt, da das Schema immer das Gleiche ist.
Wie ich auf die ersten Wert von name=route zugreife weiß ich noch. face-smile Aber wie komme ich an die Werte von name=descr und name=origin?


Gruß,
Dani

Content-ID: 292039

Url: https://administrator.de/forum/wie-kann-ich-auf-werte-eines-json-arrays-zugreifen-292039.html

Ausgedruckt am: 12.04.2025 um 17:04 Uhr

114757
114757 01.01.2016 um 11:56:12 Uhr
Goto Top
$rest.objects.object.attributes | ?{$_.Name -eq 'descr'}  

usw.

Gruß jodel32
Dani
Dani 01.01.2016 aktualisiert um 12:00:58 Uhr
Goto Top
Moin @114757,
seltsam, genau die Abfrage funktioniert bei mir nicht. Wie hast du es bei dir getestet?
Ich habe ne Powershell geöffnet, schreibe die Rückgabe in die Variable $rest und führe deine Abfrage aus.


Gruß,
Dani
114757
114757 01.01.2016 um 12:02:12 Uhr
Goto Top
Bin noch unterwegs teste nachher....
114757
Lösung 114757 01.01.2016, aktualisiert am 02.01.2016 um 17:04:18 Uhr
Goto Top
$query = 'AS3320'  
$rest = Invoke-RestMethod -Uri "http://rest.db.ripe.net/search.json?query-string=$query&inverse-attribute=origin&type-filter=route" -ContentType application/json -Method Get  
$rest.objects.object.attributes | select @{n='Description';e={($_.attribute | ?{$_.name -eq 'descr'} | select -Expand Value) -join ','}},@{n='route';e={$_.attribute | ?{$_.name -eq 'route'} | select -Expand Value}},@{n='Origin';e={$_.attribute | ?{$_.name -eq 'origin'} | select -Expand Value}} | export-csv "C:\$query.csv" -Delimiter ";" -NoType -Encoding UTF8  
colinardo
Lösung colinardo 01.01.2016, aktualisiert am 02.01.2016 um 17:04:17 Uhr
Goto Top
Hallo Dani, frohes neues face-smile

oder so für alle Felder mit Datumsumwandlung
$query = 'AS3320'  
$rest = Invoke-RestMethod -Uri "http://rest.db.ripe.net/search.json?query-string=$([System.Web.HttpUtility]::UrlEncode($query))&inverse-attribute=origin&type-filter=route" -ContentType application/json -Method Get  
$obj = @()
$rest.objects.object.attributes | %{
    $entry = @{}
    $_.attribute | %{$entry[$_.name] += $_.Value}
    $entry.'last-modified' = get-date $entry.'last-modified' -EA SilentlyContinue  
    $entry.created = get-date $entry.created -EA SilentlyContinue
    $obj += New-Object PSObject -Property $entry
}
$obj | export-csv "C:\$query.csv" -Delimiter ";" -NoType -Encoding UTF8  
Grüße Uwe
Dani
Dani 01.01.2016 aktualisiert um 16:16:02 Uhr
Goto Top
Hi Jodel32,
ohh, wow... so einfach kommt an die Werte ran. face-confused Vielen Dan erstmal dafür!
Der Operator -join ist weshalb notwendig?


Gruß,
Dani
Dani
Dani 01.01.2016 aktualisiert um 16:27:36 Uhr
Goto Top
Hallo Uwe,
vielen Dank auch an dich. Drei Fragen stellen sich:
1) Warum hast du bei der Abfrage $([System.Web.HttpUtility]::UrlEncode($query)) gesetzt?
2) Verstehe ich das richtig, dass du in deinem Beispiel über zwei foreach - Schleifen zum Ziel kommst? Die Aliase sind mir noch nicht ganz so geläufig...
3)Was genau passiert hier? Klar es wird ein neues Object erstellt aber warum.
$obj += New-Object PSObject -Property $entry


Gruß,
Dani
colinardo
colinardo 01.01.2016 aktualisiert um 16:27:06 Uhr
Goto Top
Zitat von @Dani:
Der Operator -join ist weshalb notwendig?
Weil in der Ausgabe mehrere Felder mit dem selben Namen vorhanden sind, die damit zusammengefasst werden.
Die Verteilen damit längere Zeilen auf mehrere Felder mit dem selben Namen. Das descr-Feld ist ein Beispiel.

Grüße Uwe
colinardo
colinardo 01.01.2016 aktualisiert um 16:35:47 Uhr
Goto Top
Zitat von @Dani:

Hallo Uwe,
vielen Dank auch an dich. Drei Fragen stellen sich:
1) Warum hast du bei der Abfrage $([System.Web.HttpUtility]::UrlEncode($query)) gesetzt?
Das ist Best-Practice wenn der Eingabestring $query z.B. Sonderzeichen enthält, die werden dan URL-Konform escaped/umgewandelt.

2) Verstehe ich das richtig, dass du in deinem Beispiel über zwei foreach - Schleifen zum Ziel kommst? Die Aliase sind mir noch nicht ganz so geläufig...
Ja %{} ist eine Abkürzung für eine Foreach Schleife
3)Was genau passiert hier? Klar es wird ein neues Object erstellt aber warum.
$obj += New-Object PSObject -Property $entry
Für jeden Eintrag wird eine Hashtable $entry erstellt, dieser Hashtable werden alle Felder des Eintrags hinzugefügt, doppelte werden zusammengefasst bzw. die Strings hinten angehängt.
Dann formatiere ich die beiden Datumswerte.
Und zum Schluss wird aus der Hashtable ein Custom-Object erzeugt das dem Array $obj hinzugefügt wird.
Das ist eine gängige Methode Daten für den CSV-Export aufzubereiten.
Du kannst es zwar auch wie jodel es mit Calculated Properties gezeigt hat machen, dann musst du aber jede Eigenschaft einzeln als Property hinzufügen, das macht das ganze unhandlich und etwas unübersichtlich. Mit meiner Variante erfasst du automatisch jedes Feld.
Dani
Dani 02.01.2016 um 15:11:47 Uhr
Goto Top
Hallo Uwe,
ich kann keinen Unterschied zwischen den Ausgaben mit/ohne -join feststellen.


Gruß,
Dani
Dani
Dani 02.01.2016 aktualisiert um 15:15:16 Uhr
Goto Top
Hallo Uwe,
Das ist Best-Practice wenn der Eingabestring $query z.B. Sonderzeichen enthält, die werden dan URL-Konform escaped/umgewandelt.
Unter Windows 10, Powershell 5 wird ein Fehler ausgegeben:
Der Typ [System.Web.HttpUtility] wurde nicht gefunden.

Du kannst es zwar auch wie jodel es mit Calculated Properties gezeigt hat machen, dann musst du aber jede Eigenschaft einzeln als Property hinzufügen, das macht das ganze unhandlich und etwas unübersichtlich. Mit meiner Variante erfasst du automatisch jedes Feld.
Ich benötige eigentlich nur die genannten Felder aus dem JSON-Array. Alle Anderen sind für das Vorhaben egal.


Gruß,
Dani
114757
114757 02.01.2016 aktualisiert um 15:42:16 Uhr
Goto Top
Zitat von @Dani:

ich kann keinen Unterschied zwischen den Ausgaben mit/ohne -join feststellen.

Den siehst du ja auch nur bei Feldern die mehr als einmal vorhanden sind face-wink Gerade das Description Feld kommt ja oft mehrfach vor!
Geht hier einwandfrei !
colinardo
colinardo 02.01.2016 um 15:47:04 Uhr
Goto Top
Zitat von @Dani:
ich kann keinen Unterschied zwischen den Ausgaben mit/ohne -join feststellen.
Siehe jodel32... Stichwort ist wenn mehrere Felder mit dem selben Namen auftauchen.
colinardo
colinardo 02.01.2016 aktualisiert um 15:55:21 Uhr
Goto Top
Zitat von @Dani:
Unter Windows 10, Powershell 5 wird ein Fehler ausgegeben:
Der Typ [System.Web.HttpUtility] wurde nicht gefunden.
Geht hier einwandfrei Windows 7/8/10 etc egal. Ein Importieren eines Namespaces ist hier nicht notwendig, geht out of the box!
Ich nutze das ja in all meinen Skripten, kann also nur bei dir was nicht stimmen.

Dann lasse es halt weg und machs nur mit der Variablen, wenn sie keine Sonderzeichen enthält.

Wen du nicht alle Felder brauchst machst du einfach einen select auf das $obj mit den benötigten Feldern vor dem Export, feddich.
colinardo
Lösung colinardo 02.01.2016 aktualisiert um 17:04:11 Uhr
Goto Top
p.s.
Unter Windows 10 geht aber alternativ auch
[System.Net.WebUtility]::UrlEncode($query)
geht ebenfalls ohne Import eines Namespaces!

Was'n los Dani face-smile, noch den Schampus vom Jahreswechsel intus ?
114757
114757 02.01.2016 aktualisiert um 16:21:32 Uhr
Goto Top
Zitat von @colinardo:
p.s.
Unter Windows 10 geht aber alternativ auch
> [System.Net.WebUtility]::UrlEncode($query)
> 
Joa kann ich nur zustimmen, geht hier beides unter Windows 10 ... ohne weitere Voraussetzungen.
Dani
Dani 02.01.2016 aktualisiert um 17:05:08 Uhr
Goto Top
Nehme ich die Alternative funktioniert es wie du gesagt hast:
$rest = Invoke-RestMethod -Uri "http://rest.db.ripe.net/search.json?query-string=AS$([System.Net.WebUtility]::UrlEncode($strBgpAs))&inverse-attribute=origin&type-filter=route" -ContentType application/json -Method Get  


Was'n los Dani , noch den Schampus vom Jahreswechsel intus ?
Nee... aber wenn's heut so weiter geht, heute Abend wieder face-smile
Ich habe beide Lösungen ausprobiert und das Result ist immer das Gewünschte. Persönlich gefällt mir die Lösung von @colinardo besser, da ich somit eine Funktion entwerfen kann und je nach Anwendungsfall die notwendigen Informationen aus der Rückgabevariable selektieren kann.

Vielen Dank nochmal an euch beide für die vorzügliche Unterstützung!
Ihr zwei programmiert wohl etwas öfters als ich in meiner Freizeit... face-wink


Gruß,
Danui
colinardo
colinardo 02.01.2016 aktualisiert um 17:25:34 Uhr
Goto Top
Zitat von @Dani:
Nehme ich die Alternative funktioniert es wie du gesagt hast:
Na Gott sei Dank face-smile
Bist du in einer Non-Standard PS-Session unterwegs ?
Das aktuellste Windows 10 1511 Enterprise zeigt hier nämlich überall folgendes Verhalten.

0b74927c4c0b154fb147bfcce7cf2082

Schönen Abend
Grüße Uwe