Powershell-解析不一致的Json数据

时间:2018-11-03 17:05:21

标签: json powershell parsing

我得到了一个带有ID和Json数据的CSV文件。我需要将数据解析为CustomerData类。

但是,我在访问给定键的值时遇到问题

我得到了这个CSV文件。 Json可能在某些记录中包含一些键,而在其他记录中可能不存在。基本上只存在已更新的字段。

ID;CHANGES
713422;[{"key":"zipCode","updatedValue":""},,{"key":"language","updatedValue":"EN"},{"key":"coaddress","updatedValue":""},{"key":"SSN","updatedValue":""},{"key":"msisdn","updatedValue":"1114455789"}]
114365;[{"key":"city","previousValue":"New York","updatedValue":"Palm City"},{"key":"zipcode","previousValue":"100012","updatedValue":"02118"},{"key":"coaddress","updatedValue":""},{"key":"streetaddress","previousValue":"9253 Del Monte Road"updatedValue":"90 Kent Ave"},{"key":"SSN","updatedValue":""},{"key":"companyName","previousValue":"Nutrics","updatedValue":"NutriTiger"}]
114365;[{"key":"zipCode","updatedValue":""},{"key":"coaddress","updatedValue":""},{"key":"SSN","updatedValue":""},{"key":"companyName","previousValue":"NutriTiger","updatedValue":"Nutri-Tiger"}]
713422;[{"key":"zipCode","updatedValue":""},{"key":"coaddress","updatedValue":"Roady Road"},{"key":"SSN","updatedValue":""},{"key":"msisdn","updatedValue":""}]

我想做的是这样的。 Json数据中可能会出现8个键,我需要检查它是否存在,如果存在则获取值。

$city
if (TryParse(Json.city.GetValue, $city )
{
    CustomerData.$city = Json.city.GetValue
}

这就是我现在的状态。我被困在If语句中,在这里我尝试以不同的方式访问$ jsondata。 我试过了 $ jsonData.city $ jSonData.getValue('city') 不同种类的传递$ jsonData并进行选择

但是我似乎无法获取给定键的值。

我最终需要建立一个新的CSV文件,在其中搜索ID,然后更新给定的字段,例如城市(如果已更新)。

class CustomerData
{
    [int]$Id = 0

    [string]$companyName = ""
    [string]$ssn = ""
    [string]$msisdn = ""
    [string]$language = ""

    [string]$city = ""
    [string]$coaddress = ""
    [string]$streetaddress = ""
    [string]$zipCode = ""
}

$inputdata = ".\Testdata.csv"

$iso8859_1 = [System.Text.Encoding]::GetEncoding('ISO-8859-1')

    $reader = New-Object -TypeName System.IO.StreamReader($inputdata, $iso8859_1)
    [int]$counter = 0

    while ($line = $reader.ReadLine() )
    {   

        if ($counter -gt 0)
        {
            $lines_split = $line.Split(';')
            CustomerData.$Id = $lines[0]
            $jsondata = ConvertFrom-Json $lines[1] 
        }
        $counter++;
    }
    $reader.Close()

2 个答案:

答案 0 :(得分:2)

尝试从以下代码片段中获取一些想法:

$reader = [System.IO.StringReader]::new(@'
ID;CHANGES
713422;[{"key":"zipCode","updatedValue":";"},{"key":"language","updatedValue":"EN"},{"key":"coaddress","updatedValue":""},{"key":"SSN","updatedValue":""},{"key":"msisdn","updatedValue":"1114455789"}]
114365;[{"key":"city","previousValue":"New York","updatedValue":"Palm City"},{"key":"zipcode","previousValue":"100012","updatedValue":"02118"},{"key":"coaddress","updatedValue":""},{"key":"streetaddress","previousValue":"9253 Del Monte Road","updatedValue":"90 Kent Ave"},{"key":"SSN","updatedValue":""},{"key":"companyName","previousValue":"Nutrics","updatedValue":"NutriTiger"}]
114365;[{"key":"zipCode","updatedValue":""},{"key":"coaddress","updatedValue":""},{"key":"SSN","updatedValue":""},{"key":"companyName","previousValue":"NutriTiger","updatedValue":"Nutri-Tiger"}]
713422;[{"key":"zipCode","updatedValue":""},{"key":"coaddress","updatedValue":"Roady Road"},{"key":"SSN","updatedValue":""},{"key":"msisdn","updatedValue":""}]
'@)
class CustomerData
{
  [int]$Id = 0

  [string]$companyName = ""
  [string]$ssn = ""
  [string]$msisdn = ""
  [string]$language = ""

  [string]$city = ""
  [string]$coaddress = ""
  [string]$streetaddress = ""
  [string]$zipCode = ""
}
$props = [CustomerData].GetProperties() | ForEach-Object Name
$counter = 0
while ( $line = $reader.ReadLine() )
{
  if( $counter -gt 0 )
  {
    $cd = [CustomerData]::new()
    $cd.Id, $ch = $line.Split(';')
    $ch = $ch -join ';'
    $jsondata = ConvertFrom-Json $ch
    $jsondata | Where-Object { $props -contains $_.key } |
      ForEach-Object { $cd."$($_.key)" = $_.updatedValue }
    $cd
  }
  $counter++
}
$reader.Close()

答案 1 :(得分:2)

Andrei Odegov's answer包含对代码的有益改进。
如当前所发布的,代码的主要问题是变量名混乱:将字段保存到数组$lines_split,然后错误地访问不同变量$lines

通常来说,至少默认情况下不需要{em> 类似TryParse()的东西:您可以直接访问属性路径,如果不存在,则{{ 1}}将返回:

$null

如果$bar = ('{ "foo": 1 }' | ConvertFrom-Json).bar # $bar will be $null 或更高版本有效,则访问不存在的属性的确会导致(语句终止)错误;使用Set-StrictMode -Version 2是处理此问题的最简单方法,它还允许您指定默认值

try / catch

也就是说,您的特定JSON输入以目标属性 names 位于JSON属性 values 中的方式进行构造,从而防止了诸如{{1} },因此您需要过滤对象。

但是,与其寻找特定的值,不如考虑对它们进行迭代

$bar = try { ('{ "foo": 1 }' | ConvertFrom-Json).bar } catch { 0 }  # $bar will be 0