2015-11-04 29 views
10

Powershell'de aşağıdaki JSON içinde geçiş yapmaya çalışıyorum. Üst etiketleri (örneğin, 17443, 17444) özellikle belirtmedikçe, önceden bilmediğim gibi, veriyi döngülemek için bir yol bulamıyorum.JSON File PowerShell üzerinden yineleme

Tüm kayıtlar için 3, 4 ve 5 (başlık, ad, soyadı) etiketleri çıkartmak istiyorum.

Bunu nasıl başarabilirim?

Herhangi bir yardım Ben, vb aşağıda kodla verilere erişmek, ancak 17443, 17444 yılında koyarak kaçınmak istiyor olabilir

{ 
    "17443":{ 
     "sid":"17443", 
     "nid":"7728", 
     "submitted":"1436175407", 
     "data":{ 
     "3":{ 
      "value":[ 
       "Mr" 
      ] 
     }, 
     "4":{ 
      "value":[ 
       "Jack" 
      ] 
     }, 
     "5":{ 
      "value":[ 
       "Cawles" 
      ] 
     } 
     }, 
     "17444":{ 
     "sid":"17444", 
     "nid":"7728", 
     "submitted":"1436891400", 
     "data":{ 
      "3":{ 
       "value":[ 
        "Miss" 
       ] 
      }, 
      "4":{ 
       "value":[ 
        "Charlotte" 
       ] 
      }, 
      "5":{ 
       "value":[ 
        "Tann" 
       ] 
      } 
     } 
     }, 
     "17445":{ 
     "sid":"17445", 
     "nid":"7728", 
     "submitted":"1437142325", 
     "data":{ 
      "3":{ 
       "value":[ 
        "Mr" 
       ] 
      }, 
      "4":{ 
       "value":[ 
        "John" 
       ] 
      }, 
      "5":{ 
       "value":[ 
        "Brokland" 
       ] 
      } 
     } 
     } 
    } 
} 

takdir

 $data = ConvertFrom-Json $json 

    foreach ($i in $data.17443) 
    { 
     foreach ($t in $i.data.3) 
     { 
      write-host $t.value 
     } 
     foreach ($t in $i.data.4) 
     { 
      write-host $t.value 
     } 
     foreach ($t in $i.data.5) 
     { 
      write-host $t.value 
     } 

    } 
+2

kendini bir şey denediniz alternatif New-Object PSObject -Property @{...} ile özelliklerinin bir grup ile bunu başlatmak ya da birileri bu sizin için uygulayan bekliyor olabilir? – Tomalak

+0

Evet, özellikle ($ i $ data.17443) { foreach ($ i.data.3 içinde $ t) { yazmaya karşı ev sahibi, örneğin foreach üst etiketler ekleyerek verilere alabilirsiniz $ t.value } foreach ($ i.data.4 olarak $ t) { yazma ana $ t.value } foreach ($ i.data.5 olarak $ t) { yazma konakçı $ t.value } } – Omen9876

+0

Sorumu bu ile düzenledim, bu yüzden daha yararlıdır – Omen9876

cevap

10

PowerShell 3.0

ve daha yüksek bir JSON dönüştürmek için ConvertFrom-Json cmdlet'ini kullanabilirsiniz: parçaları birleştirmek

$oRegex = [Regex]'(?:(?<="[345]":\{"value"\:\["))[^"]+' 
$cParts = $oRegex.Matches(($sRawJson -replace '\s')) | Select-Object -ExpandProperty "Value" 

tam adlarını almak için: $sRawJson varsayarsak JSON girişini içerir bir PowerShell veri yapısı içine dize. talihsiz o JSON tüketmek çok kolay olduğundan, kullanışlı, ConvertFrom-Json size PSCustomObjects verir ve onlar anahtar-değer çiftleri olarak üzerinde yineleme zor çünkü - Aynı anda uygun ve talihsiz

.

Bu özel JSON'da, anahtarlar "17443" veya "17444" gibi zamanın ön tarafında bilinmemektedir. Bu,'u foreach'un anlayabileceği bir anahtar-değer listesine dönüştürebilen bir şeye ihtiyacımız olduğu anlamına gelir.

# helper to turn PSCustomObject into a list of key/value pairs 
function Get-ObjectMembers { 
    [CmdletBinding()] 
    Param(
     [Parameter(Mandatory=$True, ValueFromPipeline=$True)] 
     [PSCustomObject]$obj 
    ) 
    $obj | Get-Member -MemberType NoteProperty | ForEach-Object { 
     $key = $_.Name 
     [PSCustomObject]@{Key = $key; Value = $obj."$key"} 
    } 
} 

Şimdi nesne grafiği çapraz ve Title, FirstName ve LastName

$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}' 

$json | ConvertFrom-Json | Get-ObjectMembers | foreach { 
    $_.Value | Get-ObjectMembers | where Key -match "^\d+$" | foreach { 
     [PSCustomObject]@{ 
      Title = $_.value.data."3".value | select -First 1 
      FirstName = $_.Value.data."4".value | select -First 1 
      LastName = $_.Value.data."5".value | select -First 1 
     } 
    } 
} 

Çıkış

 
Title      FirstName     LastName     
-----      ---------     --------     
Miss      Charlotte     Tann      
Mr       John      Brokland     

PowerShell 2.0/Alternatif bir yaklaşım ile çıkış nesnelerin bir listesi üretebilir

Ayrıca, PowerShell 2.0 için de çalışan (yukarıdaki yapıların bazılarını desteklemeyen) alternatif bir yaklaşımın kullanılması.JavaScriptSerializer yoluyla anahtar-değer çiftleri olarak üzerinde yineleme kolay düzenli Dictionaries verir çünkü, yukarıdaki gibi hatta biraz daha basit -

Add-Type -AssemblyName System.Web.Extensions 
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer 

Şimdi çok benzer bir operasyon yapabiliriz: JSON işlemek için JavaScriptSerializer class NET GetEnumerator() yöntemi:

$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}' 

$data = $JS.DeserializeObject($json) 

$data.GetEnumerator() | foreach { 
    $_.Value.GetEnumerator() | where { $_.Key -match "^\d+$" } | foreach { 
     New-Object PSObject -Property @{ 
      Title = $_.Value.data."3".value | select -First 1 
      FirstName = $_.Value.data."4".value | select -First 1 
      LastName = $_.Value.data."5".value | select -First 1 
     } 
    } 
} 

çıkışı aynıdır:

 
Title      FirstName     LastName     
-----      ---------     --------     
Miss      Charlotte     Tann      
Mr       John      Brokland     

bir dosyadan okursanızkullanmak.

  • -Raw aksi Get-Content döner bireysel hatların dizi ve JavaScriptSerializer.DeserializeObject bu idare olamaz. Son Powershell sürümleri, .NET işlev argümanları için geliştirilmiş tür dönüşümüne sahip gibi görünüyor, bu yüzden sisteminizde hata olmayabilir, ancak (veya güvenli olması için) -Raw kullanın. Bir metin dosyasının kodlamasını okurken ve UTF-8 JSON dosyaları için en olası değeri belirtmek akıllıca olduğundan,
  • .

JSON dosyalarınız 4 MB'den büyükse, JavaScriptSerializer.MaxJsonLength property'u uygun şekilde ayarlayın.


Notlar

  • ConvertFrom-Json() size JSON dize verileri yansıtan bir PowerShell özel bir nesne (PSCustomObject) verir.
  • yapabilirsiniz Get-Member -type NoteProperty
  • ile özel bir nesnenin özellikleri dinamik alternatif $object."$(some PS expression)", $object."$propName" sözdizimi kullanılarak bir nesnenin özelliklerine ulaşmak olsa döngü.
  • kendi özel nesne oluşturmak ve [PSCustomObject]@{ .. } `
+0

Teşekkür ederim, ihtiyacım olan şey bu – Omen9876

-5

Burada basit regex tabanlı çözüm . PowerShell 3.0'da

for ($i = 0; $i -lt $cParts.Count/3; $i++) { $cParts[($i * 3)..($i * 3 + 2)] -join ' ' } 
+1

JSON'a asla normal ifadelerle dokunmak istemezsiniz. – Tomalak

+0

Belki size göre. Ayrıca tam olarak ne sorduğunu kesin bir şekilde cevaplayan bir cevap aşağı doğru sadece düz yıkıcıdır. –

+1

İşe yararsız ve gereksiz şeyler yapan cevapları reddediyorum. Şans eseri tesadüf eseri olup olmadıklarına bakılmaksızın tamamen doğrudur. Ayrıca, XML veya HTML'nin normal ifadelerle ayrıştırılabileceğini öneren yanıtları da reddediyorum. Bu, JSON'un normal ifadelerle ayrıştırılamamasının nedenlerinden biri. – Tomalak

İlgili konular