【问题标题】:Powershell extract data from really weird JSON filePowershell 从非常奇怪的 JSON 文件中提取数据
【发布时间】:2023-03-06 09:18:01
【问题描述】:

我有一个非常奇怪的 json 文件,我正在尝试通过 powershell 从中提取数据。

问题是这个文件的创建者正在以一种我以前从未见过的方式使用 json:

(城市不在数组中,大陆不在数组中等)

缩短的 JSON 文件:

{
"zscloud.net": {
    "continent : EMEA": {
        "city : Abu Dhabi I": [
            {
                "range": "147.161.174.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "24.453884",
                "longitude": "54.3773438"
            }
        ],
        "city : Amsterdam II": [
            {
                "range": "185.46.212.0/23",
                "vpn": "amsterdam2-vpn.zscloud.net",
                "gre": "185.46.212.36",
                "hostname": "ams2.sme.zscloud.net",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.228.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "165.225.240.0/23",
                "vpn": "ams2-2-vpn.zscloud.net",
                "gre": "165.225.240.42",
                "hostname": "ams2-2.sme.zscloud.net",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.172.0/23",
                "vpn": "",
                "gre": "165.225.240.42",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.230.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.232.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.234.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.224.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            },
            {
                "range": "147.161.226.0/23",
                "vpn": "",
                "gre": "",
                "hostname": "",
                "latitude": "52",
                "longitude": "5"
            }
        ]
    }
}

}

我正在尝试获取城市名称 + 嵌套主机名。

我的选择:

  1. 我可以使用 Convertfrom-JSON,然后以某种方式遍历几个未知的键和属性。

  2. 或者我可以使用 select-string 并且基本上只 grep 匹配的正则表达式。然后将它们放入数组等中。

以前,我使用 select-string 来对抗美化的 JSON,因为它更容易。

今天,我发现可能不仅需要主机名,还需要主机名 + 城市名。知道如何从 json 中提取它们吗?

我在 PS5 上。

非常感谢, 紫菀

【问题讨论】:

    标签: json powershell select-string


    【解决方案1】:

    我可以使用ConvertFrom-JSON,然后以某种方式迭代几个未知的键和属性

    让我告诉你怎么做!

    PowerShell 允许您通过 psobject 隐藏成员集以编程方式发现任何对象的属性:

    PS ~> $someObject = [pscustomobject]@{ A = 123; B = "a string value" }
    PS ~> $someObject.psobject.Properties
    
    
    MemberType      : NoteProperty
    IsSettable      : True
    IsGettable      : True
    Value           : 123
    TypeNameOfValue : System.Int32
    Name            : A
    IsInstance      : True
    
    MemberType      : NoteProperty
    IsSettable      : True
    IsGettable      : True
    Value           : a string value
    TypeNameOfValue : System.String
    Name            : B
    IsInstance      : True
    

    应用于您的 JSON 输入,我们可以这样做:

    # The following assumes you've loaded the JSON into a string like below
    $json = @'
    {
        "zscloud.net": {
            "continent : EMEA": {
                "city : Abu Dhabi I": [
                    {
                        "range": "147.161.174.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "24.453884",
                        "longitude": "54.3773438"
                    }
                ],
                "city : Amsterdam II": [
                    {
                        "range": "185.46.212.0/23",
                        "vpn": "amsterdam2-vpn.zscloud.net",
                        "gre": "185.46.212.36",
                        "hostname": "ams2.sme.zscloud.net",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.228.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "165.225.240.0/23",
                        "vpn": "ams2-2-vpn.zscloud.net",
                        "gre": "165.225.240.42",
                        "hostname": "ams2-2.sme.zscloud.net",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.172.0/23",
                        "vpn": "",
                        "gre": "165.225.240.42",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.230.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.232.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.234.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.224.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    },
                    {
                        "range": "147.161.226.0/23",
                        "vpn": "",
                        "gre": "",
                        "hostname": "",
                        "latitude": "52",
                        "longitude": "5"
                    }
                ]
            }
        }
    }
    '@
    

    现在是实际代码:

    # Convert json to an object
    $data = $json |ConvertFrom-Json
    
    # Iterate over each property (cloud provider?) on the root object
    foreach($provider in $data.psobject.Properties){
      # save the provider name for later
      $providerName = $provider.Name
      # Iterate over each property (geographic region?) on the provider object
      foreach($region in $provider.Value.psobject.Properties){
        # save the region name for later, remove the `continent : ` prefix
        $regionName = $region.Name -replace '^.*?:\s*'
        # Iterate over each property (datacenter location?) on the region object
        foreach($location in $region.Value.psobject.Properties){
          # save the location name for later, remove the `city : ` prefix
          $locationName = $location.Name -replace '^.*?:\s*'
    
          # Extract the network information, attach the parent details
          $location.Value |Select-Object *,@{Name='provider';Expression={$providerName}},@{Name='region';Expression={$regionName}},@{Name='location';Expression={$locationName}},
        }
      }
    }
    

    你会得到这样的输出,更容易使用:

    range     : 147.161.174.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 24.453884
    longitude : 54.3773438
    provider  : zscloud.net
    region    : EMEA
    location  : Abu Dhabi I
    
    range     : 185.46.212.0/23
    vpn       : amsterdam2-vpn.zscloud.net
    gre       : 185.46.212.36
    hostname  : ams2.sme.zscloud.net
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.228.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 165.225.240.0/23
    vpn       : ams2-2-vpn.zscloud.net
    gre       : 165.225.240.42
    hostname  : ams2-2.sme.zscloud.net
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.172.0/23
    vpn       :
    gre       : 165.225.240.42
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.230.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.232.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.234.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.224.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    
    range     : 147.161.226.0/23
    vpn       :
    gre       :
    hostname  :
    latitude  : 52
    longitude : 5
    provider  : zscloud.net
    region    : EMEA
    location  : Amsterdam II
    

    【讨论】:

    • @aster007 太好了。如果我的回答解决了您的问题,请考虑通过单击左侧的复选标记将其标记为“已接受”:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2019-01-22
    相关资源
    最近更新 更多