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"
}
]
}
}
}
我正在尝试获取城市名称 + 嵌套主机名。
我的选择:
我可以使用 Convertfrom-JSON 然后以某种方式迭代几个未知的键和属性。
或者我可以使用 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
我有一个非常奇怪的 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"
}
]
}
}
}
我正在尝试获取城市名称 + 嵌套主机名。
我的选择:
我可以使用 Convertfrom-JSON 然后以某种方式迭代几个未知的键和属性。
或者我可以使用 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