我有一个非常奇怪的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匹配的正则表达式。然后将它们放入数组等
以前,我使用选择字符串而不是美化JSON,因为它更容易。
今天,我发现不仅需要Hostname,还需要Hostname + City name。知道如何从json中提取它们吗?
我在PS5上。
很多谢谢,Aster
我可以使用
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