В Powershell ConvertTo-Json отсутствуют квадратные скобки и добавлены новые символы - PullRequest
2 голосов
/ 22 сентября 2019

Без помощи авторов @ mklement0 и @Theo я смог получить хорошие результаты с решением, описанным в этом вопросе Проблема Powershell ConvertTo-Json с двойными кавычками .

Но из-за требований формата JSON у меня есть еще две проблемы:

  1. Значения с mac- и ip-адресами должны указываться в квадратных скобках ( [] ) и каждый из них должен быть указан между ( "" ), например:
"mac_address":  ["00:10:XX:10:00:0X", "X0:X0:11:X0:00:0X", "X0:11:X0:11:XX:11"]
В file.txt у меня также будет следующая информация о значении ключа:
product_executable : "C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE

Я использовал текущий код в вопросе, упомянутом выше, и яполучить двойной обратный слеш и новый в начале:

"product_executable":  "\"C:\\Program Files (x86)\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE\" /!REMEDIATE"

Я уже пытался обработать вывод хеш-таблицы ($ oht) безуспешно, а также пытался изменить добавление и удаление символов.

My file.txt содержит следующую структурированную информацию (также две пустые строки в начале):



adapter_name          : empty1
route_age             : 10
route_nexthop         : 172.0.0.1
route_protocol        : NETMGMT1
speed                 : null 
mac_address           : 11:10:XX:10:00:0X, X1:X0:11:X0:00:0X, X1:11:X0:11:XX:11
product_executable    : "C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE

adapter_name          : empty2
route_age             : 100
route_nexthop         : 172.0.0.2
route_protocol        : NETMGMT2
speed                 : null 
mac_address           : 22:10:XX:10:00:0X, X2:X0:11:X0:00:0X, X2:11:X0:11:XX:11
product_executable    : "C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE

adapter_name          : empty3
route_age             : 1000
route_nexthop         : 172.0.0.3
route_protocol        : NETMGMT3
speed                 : null 
mac_address           : 33:10:XX:10:00:0X, X3:X0:11:X0:00:0X, X3:11:X0:11:XX:11
product_executable    : "C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE

Текущий код (см. Упомянутый вопрос):

# Read the input file as a whole (-Raw) and split it into blocks (paragraphs)
(Get-Content -Raw C:\scripts\file.txt) -split '\r?\n\r?\n' -ne '' |
  ForEach-Object { # Process each block
    # Initialize an ordered hashtable for the key-values pairs in this block.
    $oht = [ordered] @{}
    # Loop over the block's lines.
    foreach ($line in $_ -split '\r?\n' -ne '') {
      # Split the line into key and value...
      $key, $val = $line -split ':', 2
      # ... and add them to the hashtable.
      $oht[$key.Trim()] = $val.Trim()
    }
    $oht # Output the hashtable.
  } | ConvertTo-Json

Фактический результат:

    [
      {
        "adapter_name"         : "empty1",
        "route_age"            : 10,
        "route_nexthop"        : "172.0.0.1",
        "route_protocol"       : "NETMGMT1",
        "speed"                : null,
        "mac_address"          : "11:10:XX:10:00:0X, X1:X0:11:X0:00:0X, X1:11:X0:11:XX:11",
        "product_executable"   : "\"C:\\Program Files (x86)\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE" /!REMEDIATE"
      },
      {
        "adapter_name"         : "empty2",
        "route_age"            : 100,
        "route_nexthop"        : "172.0.0.2",
        "route_protocol"       : "NETMGMT2",
        "speed"                : null,
        "mac_address"          : "22:10:XX:10:00:0X, X2:X0:11:X0:00:0X, X2:11:X0:11:XX:11",
        "product_executable"   : "\"C:\\Program Files (x86)\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE" /!REMEDIATE"
      },
      {
        "adapter_name"         : "empty3",
        "route_age"            : 1000,
        "route_nexthop"        : "172.0.0.3",
        "route_protocol"       : "NETMGMT3",
        "speed"                : null,
        "mac_address"          : "33:10:XX:10:00:0X, X3:X0:11:X0:00:0X, X3:11:X0:11:XX:11",
        "product_executable"   : "\"C:\\Program Files (x86)\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE" /!REMEDIATE"
      }
    ]

И ожидаемый результат:

    [
      {
        "adapter_name"         : "empty1",
        "route_age"            : 10,
        "route_nexthop"        : "172.0.0.1",
        "route_protocol"       : "NETMGMT1",
        "speed"                : null,
        "mac_address"          :  ["11:10:XX:10:00:0X", "X1:X0:11:X0:00:0X", "X1:11:X0:11:XX:11"],
        "product_executable"   : ""C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE"
      },
      {
        "adapter_name"         : "empty2",
        "route_age"            : 100,
        "route_nexthop"        : "172.0.0.2",
        "route_protocol"       : "NETMGMT2",
        "speed"                : null,
        "mac_address"          :  ["22:10:XX:10:00:0X", "X2:X0:11:X0:00:0X", "X2:11:X0:11:XX:11"],
        "product_executable"   : ""C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE"
      },
      {
        "adapter_name"         : "empty3",
        "route_age"            : 1000,
        "route_nexthop"        : "172.0.0.3",
        "route_protocol"       : "NETMGMT3",
        "speed"                : null,
        "mac_address"          :  ["33:10:XX:10:00:0X", "X3:X0:11:X0:00:0X", "X3:11:X0:11:XX:11"],
        "product_executable"   : ""C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE"
      }
    ]

Буду очень признателен за ваши предложения.

Ответы [ 3 ]

2 голосов
/ 22 сентября 2019

Строки в JSON могут принимать escape-последовательности.Символом для определения escape-последовательности является обратный слеш \.

Последовательности Escape полезны, среди прочего:

  • Вставка непечатаемых или пробельных символов (например, TAB или символов новой строки или null)
  • Вставка двойных кавычек " в строку (поскольку двойные кавычки начинаются и заканчиваются в строке, у вас должен быть способ сказать: «Я хочу, чтобы эта кавычка была частью строки», чтобы не завершать его).
  • Вставка буквенной обратной косой черты \ (поскольку обратная косая черта - это начало escape-последовательности, вам нужен способ сказать: «Я хочу, чтобы эта обратная реакция была part * 1019».* строки, чтобы не начинать escape-последовательность)

Поэтому в вашем примере вы видите:

"\"C:\\Program Files (x86)\\McAfee\\VirusScan Enterprise\\SHSTAT.EXE\" /!REMEDIATE"

  1. В начале у вас есть двойная кавычка " для начала строки JSON.
  2. Затем сразу после вас появляется \", который говорит: «Первый символ в этой строке является действительным "»
  3. В путях, которые сами ограничены обратной косой чертой \ вам нужно, чтобы он был двойным, чтобы его можно было интерпретировать как один обратный слеш вместо попытки интерпретировать его как escape-последовательности \P rogram Files \M cAfee \V irusScan и т. д.
  4. В конце SHSTAT.EXE вы видите следующее \", которое вставляет буквальную кавычку, заканчивающую вашу цитируемую исполняемую строку.

Короче говоря, все работает какожидается.Когда вы десериализуете JSON, все получится так, как должно!

Хотите увидеть наверняка?

$myString = @'
"C:\Program Files (x86)\McAfee\VirusScan Enterprise\SHSTAT.EXE" /!REMEDIATE
'@

Write-Host $myString

$myJsonString = $myString | ConvertTo-Json

Write-Host $myJsonString

$undoJson = $myJsonString | ConvertFrom-Json

Write-Host $undoJson
1 голос
/ 22 сентября 2019

полезный ответ briantist показывает, что значения свойства product_executable правильно JSON-закодированы.

Что касается желания превратить mac_address в массивов строк: все, что нужно, это разбить значение по строке-разделителю , на массив:

То есть вместо:

$oht[$key.Trim()] = $val.Trim()

use

$oht[$key.Trim()] = $($val.Trim() -split ', ')

Если существует вероятность того, что количество пробелов между элементами является переменным, используйте
-split ',\s*'

$(...) гарантирует, что еслиоперация -split возвращает только 1 элемент - т. е. если входные данные не содержат , - входная строка возвращается как есть, а не как одноэлементный массив.

Выше предполагается, что:

  • что все значения свойств, содержащие , , должны быть проанализированы как массивы
  • , что если mac_address содержит только одну запись, она должна бытьанализируется как скаляр.

Следующий вариант применяет разбор массива только к свойству mac_address, and всегда анализирует его значение как массив (вы можете снова окружить операцию -split с помощью $(...), чтобы изменить это):

$oht[$key.Trim()] = 
  if ($key.Trim() -eq 'mac_address') { $val.Trim() -split ', ' } else { $val.Trim() }
1 голос
/ 22 сентября 2019

Вам нужно будет преобразовать MAC-адрес в массив.

# Read the input file as a whole (-Raw) and split it into blocks (paragraphs)
(Get-Content -Raw C:\scripts\file.txt) -split '\r?\n\r?\n' -ne '' |
  ForEach-Object { # Process each block
    # Initialize an ordered hashtable for the key-values pairs in this block.
    $oht = [ordered] @{}
    # Loop over the block's lines.
    foreach ($line in $_ -split '\r?\n' -ne '') {
      # Split the line into key and value...
      $key, $val = $line -split ':', 2
      # ... and add them to the hashtable.
      if ($key -like "*mac_address*"){
        $val = @($val.Replace(' ','').split(','))
      }
      $oht[$key.Trim()] = $val.Trim()
    }
    $oht # Output the hashtable.
  } | ConvertTo-Json
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...