遍历JSON文件PowerShell [英] Iterating through a JSON file PowerShell

查看:79
本文介绍了遍历JSON文件PowerShell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在PowerShell中遍历下面的JSON文件.

I am trying to loop through the below JSON file in PowerShell.

由于没有专门命名顶部标签(例如17443和17444),因为我事先并不知道它们,所以我找不到找到遍历数据的方法.

Without specifically naming the top tags (e.g. 17443 and 17444), as I do not know them in advance I cannot find a way to loop through the data.

我想为所有记录输出标签3、4和5(标题,名字,姓氏).

I want to output tags 3, 4 and 5 (title, firstname, surname) for all the records.

我该怎么做?

{
   "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"
               ]
            }
         }
      }
   }
}

我可以使用下面的代码访问数据,但我想避免放入17443、17444等.

I can access the data with the code below, but I want to avoid putting in 17443, 17444, etc.

$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
   }
}

推荐答案

PowerShell 3.0 +

在PowerShell 3.0及更高版本中(请参阅:确定已安装的PowerShell版本),您可以使用ConvertFrom-Json cmdlet来转换将JSON字符串转换为PowerShell数据结构.

PowerShell 3.0+

In PowerShell 3.0 and higher (see: Determine installed PowerShell version) you can use the ConvertFrom-Json cmdlet to convert a JSON string into a PowerShell data structure.

这既方便又不幸-方便,因为它很容易使用JSON,不幸的是,因为ConvertFrom-Json为您提供

That's convenient and unfortunate at the same time - convenient, because it's very easy to consume JSON, unfortunate because ConvertFrom-Json gives you PSCustomObjects, and they are hard to iterate over as key-value pairs.

在此特定的JSON中,键似乎是动态的/事先未知,例如"17443""17444".这意味着我们需要能够将PSCustomObject转换为foreach可以理解的键值列表的东西.

In this particular JSON, the keys seem to be dynamic/not known ahead of time, like "17443" or "17444". That means we need something that can turn a PSCustomObject into a key-value list that foreach can understand.

# 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"}
    }
}

现在我们可以遍历对象图并生成具有TitleFirstNameLastName

Now we can traverse the object graph and produce a list of output objects with Title, FirstName and 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
        }
    }
}

输出


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


PowerShell 2.0/替代方法

一种适用于PowerShell 2.0(不支持上述某些构造)的替代方法将涉及使用.NET


PowerShell 2.0 / Alternative approach

An alternative approach that also works for PowerShell 2.0 (which does not support some of the constructs above) would involve using the .NET JavaScriptSerializer class to handle the JSON:

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

现在,我们可以做一个非常类似的操作-比上面的操作更简单,因为JavaScriptSerializer为您提供常规的

Now we can do a very similar operation—even a bit simpler than above, because JavaScriptSerializer gives you regular Dictionaries, which are easy to iterate over as key-value pairs via the GetEnumerator() method:

$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
        }
    }
}

输出相同:


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

如果您的JSON大于4 MB,请设置

If you have JSON larger than 4 MB, set the JavaScriptSerializer.MaxJsonLength property accordingly.

如果您从文件中读取,请使用Get-Content -Raw -Encoding UTF-8.

If you read from a file, use Get-Content -Raw -Encoding UTF-8.

  • -Raw,因为否则Get-Content返回单个行的数组,而JavaScriptSerializer.DeserializeObject无法处理.最新的Powershell版本似乎对.NET函数参数进行了改进的类型转换,因此它可能不会在您的系统上出错,但是如果这样做(或者为了安全起见),请使用-Raw.
  • -Encoding是因为明智的做法是在读取文本文件时指定其编码,并且UTF-8是JSON文件最可能的值.
  • -Raw because otherwise Get-Content returns an array of individual lines and JavaScriptSerializer.DeserializeObject can't handle that. Recent Powershell versions seem to have improved type-conversion for .NET function arguments, so it might not error out on your system, but if it does (or just to be safe), use -Raw.
  • -Encoding because it's wise to specify a text file's encoding when you read it and UTF-8 is the most probable value for JSON files.
  • ConvertFrom-Json()为您提供了一个PowerShell定制对象(PSCustomObject),该对象反映了JSON字符串中的数据.
  • 您可以使用Get-Member -type NoteProperty
  • 遍历自定义对象的属性
  • 您可以使用$object."$propName"语法或$object."$(some PS expression)"语法动态访问对象的属性.
  • 您可以创建自己的自定义对象,并使用New-Object PSObject -Property @{...}[PSCustomObject]@{ .. }的一系列属性对其进行初始化. `
  • ConvertFrom-Json() gives you a PowerShell custom object (PSCustomObject) that reflects the data in the JSON string.
  • You can loop though the properties of a custom object with Get-Member -type NoteProperty
  • You can access the properties of an object dynamically using the $object."$propName" syntax, alternatively $object."$(some PS expression)".
  • You can create your own custom object and initialize it with a bunch of properties with New-Object PSObject -Property @{...}, alternatively [PSCustomObject]@{ .. } `

这篇关于遍历JSON文件PowerShell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆