tl;博士
该问题不影响PowerShell (Core) 6+(按需安装、跨平台 PowerShell 版本),它使用基于Newtonsoft.JSONConvertTo-Json
的不同实现和cmdlet (其直接使用显示在r3verse 的答案中) ),从 Powershell 7.2 开始。在那里,您的示例往返命令按预期工作。ConvertFrom-Json
仅ConvertTo-Json
在Windows PowerShell中受到影响(与 Windows PowerShell 捆绑的版本,其最新和最终版本为 5.1)。但请注意,JSON 表示(虽然出乎意料)在技术上是正确的。
一个简单但强大的解决方案只专注于对那些ConvertTo-Json
意外创建的 Unicode 转义序列进行转义 - 即 for & ' < >
- 同时排除误报:
# The following sample JSON with undesired Unicode escape sequences for `& < > '`, was
# created with Windows PowerShell's ConvertTo-Json as follows:
# ConvertTo-Json "Ten o'clock at <night> & later. \u0027 \\u0027"
# Note that \u0027 and \\u0027 are NOT Unicode escape sequences and must not be
# interpreted as such.
# The *desired* JSON representation - without the unexpected escaping - would be:
# "Ten o'clock at <night> & later. \\u0027 \\\\u0027"
$json = '"Ten o\u0027clock at \u003Cnight\u003e \u0026 later. \\u0027 \\\\u0027"'
[regex]::replace(
$json,
'(?<=(?:^|[^\\])(?:\\\\)*)\\u(00(?:26|27|3c|3e))',
{ param($match) [char] [int] ('0x' + $match.Groups[1].Value) },
'IgnoreCase'
)
上面输出了所需的 JSON 表示,没有不必要的转义:
"Ten o'clock at <night> & later. \\u0027 \\\\u0027"
背景资料:
ConvertTo-Json
在Windows PowerShell中,意外地通过JSON 字符串中的 Unicode 转义序列表示以下 ASCII 范围字符:
&
(Unicode 转义序列\u0026
:)
'
( \u0027
)
<
和>
(\u003c
和\u003e
)
这样做没有充分的理由(这些字符只需要在 HTML/XML 文本中转义)。
然而,任何兼容的 JSON 解析器——包括ConvertFrom-Json
——将这些转义序列转换回它们所代表的字符。
换句话说:虽然由 Windows PowerShell 创建的 JSON 文本ConvertTo-Json
是出乎意料的并且可能会妨碍可读性,但它在技术上是正确的,并且 - 虽然不完全相同-就其所代表的数据而言等同于原始表示。
修复可读性问题:
顺便说一句:虽然[regex]::Unescape()
它的目的是仅对正则表达式进行转义,但它也将 Unicode 转义序列转换为它们所代表的字符,但它从根本上不适合选择性地对 Unicode 序列JSON字符串进行转义,因为必须保留所有其他 转义符才能使用 JSON字符串保持语法有效。\
虽然您的答案通常效果很好,但它有局限性(除了容易纠正的问题,a-zA-Z
应该a-fA-F
限制匹配那些有效的十六进制数字的字母):
有关克服这些限制的强大解决方案,请参阅此答案
(代理对保留为 Unicode 转义序列,其字符需要转义的 Unicode 转义序列将转换为\
基于 - 的(C 样式)转义,例如\n
,如果可能的话)。
ConvertTo-Json
但是,如果唯一的要求是取消转义 Windows PowerShell意外创建的那些 Unicode 转义序列,那么顶部的解决方案就足够了。