Powershell 从非常奇怪的 JSON 文件中提取数据

Powershell extract data from really weird JSON file

我有一个非常奇怪的 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 字符串来对抗美化的 JSON,因为它更容易。

今天,我发现不仅需要主机名,还需要主机名+城市名。知道如何从 json?

中提取它们吗

我在 PS5.

非常感谢, 紫苑

I can either use ConvertFrom-JSON and then somehow iterate over several unknown Keys and Properties.

让我告诉你怎么做!

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