当前位置: 首页 > 面试题库 >

遍历JSON文件PowerShell

殷承恩
2023-03-14
问题内容

我试图在PowerShell中遍历以下JSON文件。

如果没有专门命名顶部标签(例如17443和17444),由于我事先不知道它们的名称,就无法找到遍历数据的方法。

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

我该怎么做?

{
   "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等。

$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版本),可以使用ConvertFrom- Jsoncmdlet将JSON字符串转换为PowerShell数据结构。

这既方便又不幸-方便,因为它很容易使用JSON,不幸的是,由于ConvertFrom- Json给了您PSCustomObjects,它们很难作为键值对进行迭代。

当您知道键之后,就没有什么要迭代的了–您只需直接访问它们,例如$result.thisKey.then.thatKey.array[1],就可以完成。

但是在此特定的JSON中,键似乎是动态的/不为人所知,例如"17443""17444"。这意味着我们需要可以将其PSCustomObject变成foreach可以理解的键值列表的东西。

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

现在,我们可以遍历对象图并使用TitleFirstName和生成输出对象列表。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
        }
    }
}

输出量

标题名姓                 
----- --------- --------                 
夏洛特·坦恩小姐                     
约翰·布罗克兰先生

PowerShell 2.0 /替代方法

另一种适用于PowerShell 2.0的替代方法(不支持上述某些构造)将涉及使用.NET
JavaScriptSerializer类来处理JSON:

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

现在我们可以做一个非常类似的操作-
比上面的操作还要简单一些,因为JavaScriptSerializer为您提供了常规的Dictionary,这些字典很容易通过以下GetEnumerator()方法作为键值对进行迭代:

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

输出是相同的:

标题名姓                 
----- --------- --------                 
夏洛特·坦恩小姐                     
约翰·布罗克兰先生

如果JSON大于4
MB,则相应地设置JavaScriptSerializer.MaxJsonLength属性。

从文件读取JSON时

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

  • -Raw因为否则Get-Content返回一个单独行的数组,JavaScriptSerializer.DeserializeObject将无法处理。最新的Powershell版本似乎对.NET函数参数进行了改进的类型转换,因此它可能不会在您的系统上出错,但是如果这样做(或者为了安全起见),请使用-Raw
  • -Encoding因为在阅读时指定文本文件的编码是明智的做法,并且这UTF-8是JSON文件最可能的值。

笔记

  • 构建包含包含具有不可预测键的项的JSON时,请优先选择像{items: [{key: 'A', value: 0}, {key: 'B', value: 1}]}over 这样的数组结构{'A': 0, 'B': 1}。后者似乎更直观,但既难以生成又难以使用。
  • ConvertFrom-Json()为您提供一个PSCustomObject可反映JSON字符串中数据的PowerShell自定义对象()。
  • 您可以通过以下方式循环自定义对象的属性: Get-Member -type NoteProperty
  • 您可以使用$object."$propName"语法动态地访问对象的属性$object."$(some PS expression)"
  • 您可以创建自己的自定义对象,并使用New-Object PSObject -Property @{...},或[PSCustomObject]@{ .. } `


 类似资料:
  • 问题内容: 我有一个带有一些数组的JSON文件。我想遍历文件数组并获取它们的元素和它们的值。 这是我的文件的样子: 这是我走了多远: 是否可以做这样的事情? 我要这样做的原因是因为文件中的数组具有不同数量的元素。 问题答案: 更改 至 或者 取决于您使用的是JSON到/来自Java的库。(看起来将为您工作。) 然后,要访问“对象”中的字符串元素,请按元素名称将其取出。 如果需要中的元素名称,则可以

  • 本文向大家介绍Python遍历文件夹 处理json文件的方法,包括了Python遍历文件夹 处理json文件的方法的使用技巧和注意事项,需要的朋友参考一下 有两种做法:os.walk()、pathlib库,个人感觉pathlib库的path.glob用来匹配文件比较简单。 下面是第二种做法的实例(第一种做法百度有很多文章): 运行结果 目录结构 json file内容 以上这篇Python遍历文件

  • 问题内容: 我正在尝试遍历JSON对象以导入数据,即标题和链接。我似乎无法掌握过去的内容。 JSON: 我尝试使用字典: 此代码仅在之前打印信息。( 忽略贾斯汀·比伯的曲目 :) 问题答案: 您加载JSON数据有些脆弱。代替: 您实际上应该这样做: 您不应该将“ JSON对象”视为什么。您所拥有的是清单。该列表包含两个字典。字典包含各种键/值对,所有字符串。当您这样做时,您将要求列表中的第一个字典

  • 问题内容: 我试图遍历并拾取目录中的文件,但是在实现它时遇到了一些麻烦。如何提取多个文件,然后将它们移动到另一个文件夹? 问题答案: 带回调的旧答案 您想要使用fs.readdir函数获取目录内容,并使用fs.rename函数实际执行重命名。如果您 需要 等待它们完成之后再运行代码,则这两个函数都具有同步版本。 我写了一个快速脚本来完成您所描述的。 在我的本地机器上测试。 更新:fs.promis

  • 问题内容: 我试图遍历此以获取“名称”值。这是我目前所拥有的,但是似乎没有用,从此处发布的内容中尝试了一些其他方法,但似乎无济于事。 Json被退回: 我试过使用: 有什么建议? 谢谢! 问题答案: 您必须将字符串解析为JSON(这实际上是字符串,而不是对象的指示):

  • 问题内容: 我很难找到一种以我想要的方式遍历此JSON对象的方法。我在这里只使用Javascript。 首先,这是对象 现在,我正在尝试基本方法来访问此对象上的每个dialog_trunk。理想情况下,我想遍历对象,并为每个主干显示其值。 我已经尝试过使用for循环动态地生成dialog_trunk的名称/编号,但是我无法使用对象名称的字符串来访问该对象,因此我不确定从何处去。 问题答案: 为此使