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;
Это предотвратит &
превращается:)