Powershell - анализ несовместимых данных Json - PullRequest
0 голосов
/ 03 ноября 2018

Я получил файл CSV с идентификатором и данными Json. Мне нужно проанализировать данные в классе 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 ( 'город') Различные виды конвейерной обработки $ jsonData и выбора

Но я просто не могу получить значение для данного ключа.

В конечном итоге мне нужно создать новый CSV-файл, в котором я ищу идентификатор, а затем обновить данное поле, например город, если он был обновлен.

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 голосов
/ 04 ноября 2018

Ответ Андрея Одегова содержит полезные улучшения вашего кода.
Как написано в настоящее время, основная проблема с вашим кодом - путаница с именем переменной: вы сохраняете поля в массиве $lines_split, а затем по ошибке получаете доступ к переменной другая , $lines.

Вообще говоря, по крайней мере по умолчанию нет необходимости в чем-то похожем на TryParse(): вы можете просто получить доступ к пути свойства, и если его не существует, $null будет вернулся:

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

Если действует Set-StrictMode -Version 2 или выше, доступ к несуществующему свойству вызывает ошибку (завершение оператора); использование try / catch - это самый простой способ справиться с этим, который также позволяет вам указать значение по умолчанию :

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

Тем не менее, ваш конкретный вход JSON структурирован таким образом, что целевое свойство names находится в свойстве JSON values ​​, что запрещает прямой доступ, такой как $obj.City, поэтому вы нужно фильтровать объекты.

Однако вместо поиска конкретных значений рассмотрим итерирование по ним :

# Instantiate a new customer-data object.
$customer = [CustomerData]::new()

# Parse the JSON data in custom objects ([pscustomobject]).
# In this case, you'll get a single-element array containing an array
# of [pscustomobject] instances.
$jsondata = ConvertFrom-Json '[{"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"}]'


# Loop over all custom objects and update the corresponding
# customer-data properties.
foreach($obj in $jsonData) {
   $propName = $obj.key
   $customer.$propName = $obj.UpdatedValue
}
0 голосов
/ 03 ноября 2018

Попробуйте получить некоторые идеи из следующего фрагмента:

$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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...