我正在尝试解析一个JSON字符串,该字符串已经从关系数据集中展开,从它的外观...转换为CSV以便导入到Oracle数据库中。我有与此(简化)示例类似的名称/值对
Device.1.Service.1.Channel.1.someProperty : 1,
Device.1.Service.1.Channel.1.someOtherProperty : "billy",
Device.1.Service.1.Channel.2.someProperty : 8,
Device.1.Service.1.Channel.2.someOtherProperty : "frank",
Device.1.Service.1.Channel.3.someProperty : 12,
Device.1.Service.1.Channel.3.someOtherProperty : "sam",
Device.1.Service.2.Channel.1.someProperty : 3,
Device.1.Service.2.Channel.1.someOtherProperty : "john",
编辑:每台设备每天生成一个具有类似结构的.json文件。因此,当合并(Get-Content .\*.json -Raw
)时,我看到在控制台中多次出现相同的属性名称。
作为转换的一部分,我希望属性名称的一部分成为数据库中的字段。这将使我们能够使用动态滑块过滤器等更好地可视化数据。
| Device | Service | Channel | someOtherProperty | | 1 | 1 | 1 | billy | | 1 | 1 | 2 | frank | | 1 | 1 | 3 | sam |
现在,我正在使用cmdlet ConvertFrom-Json
。然后,我使用通配符选择字段(在近2000个可能的字段中)。例如,频道数是动态的。
Get-Content .\*.json -Raw | ConvertFrom-Json |
Select Device.1.Service.1.Channel.?.someOtherProperty
返回PSCustomObject
。我想找出频道号并将其用作派生字段。伪示例:
Select @{n="Channel";e={$_.getCharAtWildcard()}},
$_.theValueofTheCurrentObject()
如果我将所选数据(使用通配符)传输到Get-Member
,PSCostomObject
包含方法名称和我的字段名称(但不包含值)。
我对如何访问字段名称感到困惑(因为'Name'给出空白行),然后提取通道号(通配符位置的字符),然后正确地构造输出的值。
任何指针?谷歌搜索并有一个lynda.com子,但似乎无法找到这个特定问题的解决方案 - 可能是因为我没有使用正确的条款?
## ANSGAR's SOLUTION - WORKS FOR SINGLE FILE ##
$dataDir = "C:\ps_json2csv\dummydata"
CD $dataDir
$dict = Get-Content .\*.json -Raw | ConvertFrom-Json | Select -Expand data
$p = 'DvbId'
$re = "frontend\.(\d+)\.logicalchannel\.(\d+)\.service\.(\d+)\..*?\.$p"
## modified regex to match my data, example string: FrontEnd.2.LogicalChannel.3.Service.1.stat.DvbId
$fullset = $dict.PSObject.Properties | Where-Object {
$_.Name -match $re
} | ForEach-Object {
$prop = [ordered]@{
FrontEnd = $matches[1]
LogicalChannel = $matches[2]
Service = $matches[3]
$p = $_.Value
}
New-Object -Type PSObject -Property $prop
}
## inspect $dict - its populated
## inspect $fullset - its empty! :(
其中的数据是 C:\ ps_json2csv \ dummydata 中包含的2个文件:
File1.json
{
"data": {
"Device.1.Service.1.ChannelInfo.Channel.1.Stats.someProperty" : "1",
"Device.1.Service.1.ChannelInfo.Channel.2.Stats.someProperty" : "8",
"Device.1.Service.1.ChannelInfo.Channel.3.Stats.someProperty" : "12",
"FrontEnd.2.LogicalChannel.3.Service.1.stat.DvbId" : "john",
"FrontEnd.2.LogicalChannel.3.Service.2.stat.DvbId" : "billy",
"FrontEnd.2.LogicalChannel.3.Service.3.stat.DvbId" : "frank",
"FrontEnd.2.LogicalChannel.4.Service.1.stat.DvbId" : "sam",
"Device.1.Service.2.ChannelInfo.Channel.1.Stats.someProperty" : "3",
"Some.value.im.not.intersted.in.just.yet": "Sat Jan 1 00:00:00 GMT 0001",
"foo.bar" : "0",
"random.stuff" : "hi there"
}
}
File2.json
{
"data": {
"Device.1.Service.1.ChannelInfo.Channel.1.Stats.someProperty" : "0",
"Device.1.Service.1.ChannelInfo.Channel.2.Stats.someProperty" : "7",
"Device.1.Service.1.ChannelInfo.Channel.3.Stats.someProperty" : "6",
"FrontEnd.2.LogicalChannel.3.Service.1.stat.DvbId" : "john",
"FrontEnd.2.LogicalChannel.3.Service.2.stat.DvbId" : "billy",
"FrontEnd.2.LogicalChannel.3.Service.3.stat.DvbId" : "frank",
"FrontEnd.2.LogicalChannel.4.Service.1.stat.DvbId" : "sam",
"Device.1.Service.2.ChannelInfo.Channel.1.Stats.someProperty" : "4",
"Some.value.im.not.intersted.in.just.yet": "Sun Jan 2 00:00:00 GMT 0001",
"foo.bar" : "0",
"random.stuff" : "hi there"
}
}
答案 0 :(得分:0)
我宁愿将此语法的字符串转换为具有整套属性的PSObject
。像这样:
$dict=Get-Content .\*.json -Raw | ConvertFrom-Json
$fullset=$dict.psobject.properties | % {
$parse=$_.name.split('.')
$parse+=,$_.value # since JSON values might be non-plain, we need to add the value as single object
$obj=new-object psobject
for ($i=0;$i -lt $parse.length;$i+=2) { # name-value
$v1=$parse[$i]
$v2=$parse[1+$i]
$obj | add-member -type noteproperty -name $v1 -value $v2
}
$obj
}
然后你就像使用$fullset
等普通列表一样解析where {$_.device -eq '1' -and $_.someOtherProperty -ne $null}
。
答案 1 :(得分:0)
我可能会使用正则表达式匹配来过滤和提取数据:
$p = 'someOtherProperty'
$re = "device\.(\d+)\.service\.(\d+)\..*?\.channel\.(\d+)\..*?\.$p"
$fullset = $dict.PSObject.Properties | Where-Object {
$_.Name -match $re
} | ForEach-Object {
$prop = [ordered]@{
Device = $matches[1]
Service = $matches[2]
Channel = $matches[3]
$p = $_.Value
}
New-Object -Type PSObject -Property $prop
}