【问题标题】:Powershell not able to convert while converting values from "&" to JSON将值从“&”转换为 JSON 时,Powershell 无法转换
【发布时间】:2019-05-07 17:31:57
【问题描述】:

角色全路径

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'

有什么帮助吗?

【问题讨论】:

    标签: json powershell csv


    【解决方案1】:

    Windows PowerShell v5.1 中,ConvertTo-Json 确实意外地将 & 字符编码为 Unicode 转义序列 \u0026,其中 0026 表示十六进制。数字 0x26,表示 & character, U+0026 的 Unicode 代码点。
    (相比之下,PowerShell Core 保留了 & 原样。)

    也就是说,JSON 解析器应该能够解释这样的转义序列,事实上,互补的 ConvertFrom-Json cmdlet 是。

    • 注意:下面的解决方案是通用的,可以处理any Unicode字符的Unicode转义序列;由于 ConvertTo-Json 似乎只对字符 &'<> 使用这些 Unicode 转义序列表示,因此更简单的解决方案是可能,除非必须排除误报 - 请参阅this answer

    也就是说,如果您确实想手动将 Unicode 转义序列转换为 JSON 文本中的等效字符,您可以使用以下 - 有限的解决方案:

    # Sample JSON with Unicode escapes.
    $json = '{ "roleFullPath":  "Applications\\User Admin \u0026 Support-DEMO" }'
    
    # Replace Unicode escapes with the chars. they represent,
    # with limitations.
    [regex]::replace($json, '\\u[0-9a-fA-F]{4}', { 
      param($match) [char] [int] ('0x' + $match.Value.Substring(2)) 
    })
    

    以上产出:

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

    注意\u0026 是如何转换为字符的。它代表&

    稳健的解决方案需要更多工作:

    • 有些字符必须在 JSON 中转义并且不能按字面意思表示,所以为了 to-character 转换能够正常工作 ,这些字符必须排除

    • 此外,必须避免误报;例如,\\u0026不是有效的 Unicode 转义序列,因为 JSON 解析器将 \\ 解释为转义的 \,后跟逐字的 u0026

    • 最后,"\ 的 Unicode 序列必须被翻译成它们的 转义 形式,\"\\,并且可以表示几个 ASCII 范围通过 C 样式的转义序列控制字符,例如,\t 用于制表符 (\u0009)。

    以下稳健的解决方案解决了所有这些问题:

    # Sample JSON with Unicode escape sequences:
    #  \u0026 is &, which CAN be converted to the literal char.
    #  \u000a is a newline (LF) character, which CANNOT be converted, but can
    #  be translated to escape sequence "\n"
    # \\u0026 is *not* a Unicode escape sequence and must be preserved as-is.
    $json = '{ 
      "roleFullPath": "Applications\u000aUser Admin \u0026 Support-DEMO-\\u0026" 
    }'
    
    [regex]::replace($json, '(?<=(?:^|[^\\])(?:\\\\)*)\\u([0-9a-fA-F]{4})', {
      param($match)
      $codePoint = [int] ('0x' + $match.Groups[1].Value)
      if ($codePoint -in 0x22, 0x5c) { 
        # " or \ must be \-escaped.
        '\' + [char] $codePoint
      } 
      elseif ($codePoint -in 0x8, 0x9, 0xa, 0xc, 0xd) { 
        # Control chars. that can be represented as short, C-style escape sequences.
        ('\b', '\t', '\n', $null, '\f', '\r')[$codePoint - 0x8]
      }
      elseif ($codePoint -le 0x1f -or [char]::IsSurrogate([char] $codePoint)) {
        # Other control chars. and halves of surrogate pairs must be retained
        # as escape sequences.
        # (Converting surrogate pairs to a single char. would require much more effort.)
        $match.Value
      }
      else {
        # Translate to literal char.
        [char] $codePoint
      }
    })
    

    输出:

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

    【讨论】:

      【解决方案2】:

      要阻止 Powershell 执行此操作,您的 Json 输出会通过此管道

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

      这将防止&amp; 被转换:)

      【讨论】:

      • 虽然 [regex]::Unescape() 方便地将 Unicode 转义序列转换为它们所代表的实际字符,但如果它包含 @ 的其他实例,则将此方法应用于 JSON 文本会将其作为 JSON 无效 987654324@ 个字符,例如问题中的\\ sequence。
      猜你喜欢
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 2019-12-28
      相关资源
      最近更新 更多