我有一个包含某些属性的文件,其中一些属性的值包含转义字符,例如一些Urls和Regex模式。
在阅读内容并转换回json时,无论有没有取消内容,内容都不正确。如果我用unescaping转换回json,一些正则表达式中断,如果我转换为unescaping,url和一些正则表达式将会中断。
我该如何解决这个问题?
MCVE
以下是一些简单的代码块,可让您简单地重现问题:
内容
$fileContent =
@"
{
"something": "http://domain/?x=1&y=2",
"pattern": "^(?!(\\`|\\~|\\!|\\@|\\#|\\$|\\||\\\\|\\'|\\\")).*"
}
"@
使用Unescape
如果我阅读内容,然后使用以下命令将内容转换回json:
$fileContent | ConvertFrom-Json | ConvertTo-Json | %{[regex]::Unescape($_)}
输出(错误)将是:
{
"something": "http://domain/?x=1&y=2",
"pattern": "^(?!(\|\~|\!|\@|\#|\$|\||\\|\'|\")).*"
}
没有Unescape
如果我阅读内容,然后使用以下命令将内容转换回json:
$fileContent | ConvertFrom-Json | ConvertTo-Json
输出(错误)将是:
{
"something": "http://domain/?x=1\u0026y=2",
"pattern": "^(?!(\\|\\~|\\!|\\@|\\#|\\$|\\||\\\\|\\\u0027|\\\")).*"
}
答案 0 :(得分:6)
我决定不使用Unscape
,而是使用字符串值替换unicode \uxxxx
字符,现在它可以正常运行:
$fileContent =
@"
{
"something": "http://domain/?x=1&y=2",
"pattern": "^(?!(\\`|\\~|\\!|\\@|\\#|\\$|\\||\\\\|\\'|\\\")).*"
}
"@
$fileContent | ConvertFrom-Json | ConvertTo-Json | %{
[Regex]::Replace($_,
"\\u(?<Value>[a-zA-Z0-9]{4})", {
param($m) ([char]([int]::Parse($m.Groups['Value'].Value,
[System.Globalization.NumberStyles]::HexNumber))).ToString() } )}
生成预期输出:
{
"something": "http://domain/?x=1&y=\\2",
"pattern": "^(?!(\\|\\~|\\!|\\@|\\#|\\$|\\||\\\\|\\'|\\\")).*"
}
答案 1 :(得分:2)
如果不想依靠Regex(来自@Reza Aghaei的答案),则可以导入Newtonsoft JSON库。好处是默认的StringEscapeHandling属性仅转义控制字符。另一个好处是避免了使用Regex进行潜在的危险字符串替换。
此StringEscapeHandling
也是PowerShell Core(版本6及更高版本)的默认处理方式,因为从那时起,他们开始在内部使用Newtonsoft。因此,另一种替代方法是使用PowerShell Core中的ConvertFrom-Json和ConvertTo-Json。
如果您导入Newtonsoft JSON库,您的代码将类似于以下内容:
[Reflection.Assembly]::LoadFile("Newtonsoft.Json.dll")
$json = Get-Content -Raw -Path file.json -Encoding UTF8 # read file
$unescaped = [Newtonsoft.Json.Linq.JObject]::Parse($json) # similar to ConvertFrom-Json
$escapedElementValue = [Newtonsoft.Json.JsonConvert]::ToString($unescaped.apiName.Value) # similar to ConvertTo-Json
$escapedCompleteJson = [Newtonsoft.Json.JsonConvert]::SerializeObject($unescaped) # similar to ConvertTo-Json
Write-Output "Variable passed = $escapedElementValue"
Write-Output "Same JSON as Input = $escapedCompleteJson"