Powershell не может конвертировать при преобразовании значений из "&" в JSON

RoleFullPath

Applications\User Admin & Support-DEMO

Код PowerShell

$NewJSON.roleFullPath = $Line.RoleFullPath
.
.
.
.
$JSONPath = $RolePath + $FolderName  + "-JSON.json"   
Convertto-JSON $NewJSON | Out-file -Encoding "UTF8" $JSONPath

Выход:

"roleFullPath":  "Applications\\User Admin \u0026 Support-DEMO"

При преобразовании из CSV в JSON символ '&' преобразуется в '\ u0026'

Любая помощь?

1 ответ

В Windows PowerShell v5.1 ConvertTo-Json действительно неожиданно кодирует & символы как escape-последовательность Unicode \u0026, где 0026 представляет собой гекс число 0x26кодовая точка Unicode, представляющая & персонаж,U+0026,
(PowerShell Core, напротив, сохраняет & как есть.)

Тем не менее, парсеры JSON должны быть в состоянии интерпретировать такие escape-последовательности и, действительно, дополняющие ConvertFrom-Json командлет есть.

Тем не менее, если вы хотите вручную преобразовать escape-последовательности Unicode в их символьные эквиваленты в тексте JSON, вы можете использовать следующее:

# Sample JSON with Unicode escapes.
$json = '{ "roleFullPath":  "Applications\\User Admin \u0026 Support-DEMO" }'

# Replace Unicode escapes with the chars. they represent.
[regex]::replace($json, '\\u[0-9a-f]{4}', { 
  param($match) [char] [int] ('0x' + $match.Value.Substring(2)) 
})

Вышеуказанные выходы:

{ "roleFullPath": "Applications\\User Admin & Support-DEMO" }

Обратите внимание, как \u0026 был преобразован в полукокса это представляет, &,

Предостережение:

Существуют символы, которые должны быть экранированы в JSON и не могут быть представлены в буквальном смысле, поэтому для того, чтобы преобразование в символы работало в общем, эти символы должны быть исключены:

# Sample JSON with Unicode with:
#  & encodes as \u0026, which CAN be converted
#  a newline encoded as \u000A, which CANNOT be converted (though
#  you could translate it to '\n')
$json = '{ "roleFullPath": "Applications\u000aUser Admin \u0026 Support-DEMO" }'

# Replace Unicode escapes with the chars. they represent,
# but only if it's safe to do so.
[regex]::replace($json, '\\u[0-9a-f]{4}', { 
  param($match)
  $codePoint = [int] ('0x' + $match.Value.Substring(2))
  if ($codePoint -le 0x1f -or $codePoint -in 0x22, 0x5c) {
    $match.Value # retain escape sequence
  } else { # translate to literal char.
    [char] $codePoint
  }
})

Как упоминалось в комментариях, этот подход можно усовершенствовать, обнаруживая кодовые точки, которые имеют escape-последовательности в стиле C, такие как \n за \u000Aи выводи те. Так же, " а также \ представлен как \u0022\u005c можно перевести на \" а также \\,

Чтобы Powershell не делал эту трубу, ваш вывод Json через этот

$jsonOutput | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Set-Content $jsonPath -Encoding UTF8;

Это предотвратит & превращается:)

Другие вопросы по тегам