带有双引号的 Powershell ConvertTo-Json 问题 [英] Powershell ConvertTo-Json problem with double-quotation marks

查看:73
本文介绍了带有双引号的 Powershell ConvertTo-Json 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将文本文件转换为 JSON 格式的字符串,但双引号未正确定位.

我的 file.txt 包含以下结构化信息(开头还有两个空行):

适配器名称:empty1路线年龄:10路由下一跳:172.0.0.1路由协议:NETMGMT1速度:空

适配器名称:empty2路线年龄:100路由下一跳:172.0.0.2路由协议:NETMGMT2速度:空

适配器名称:empty3路线年龄:1000路由下一跳:172.0.0.3路由协议:NETMGMT3速度:空

我的代码是:

$data = Get-Content C:\scripts\file.txt |%{$_.PSObject.BaseObject}$数据|ConvertTo-Json

没有这部分:

%{$_.PSObject.BaseObject}

它只是深入到可能需要很长时间的对象树中.

实际结果是:<预><代码>["","","adapter_name : empty1",路线年龄:10","route_nexthop : 172.0.0.1","route_protocol : NETMGMT1",速度:空""","adapter_name : empty2",路线年龄:100","route_nexthop : 172.0.0.2","route_protocol : NETMGMT2",速度:空""","adapter_name : empty3",路线年龄:1000","route_nexthop : 172.0.0.3","route_protocol : NETMGMT3",速度:空"]

预期的结果是:

<预><代码>[{"adapter_name": "empty1",路线年龄":10,"route_nexthop": "172.0.0.1","route_protocol": "NETMGMT1",速度":空},{"adapter_name": "empty2",路线年龄":100,"route_nexthop": "172.0.0.2","route_protocol" : "NETMGMT2",速度":空},{"adapter_name": "empty3",路线年龄":1000,"route_nexthop": "172.0.0.3","route_protocol": "NETMGMT3",速度":空}]

链接中的示例 4 和 5 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-6 显示如何使用 cmdletConvertoTo-Json 与类似的情况,但没有问题.

解决方案

Get-Content 仅返回文本文件中的各个行,它对这些行中可能编码的任何结构一无所知.

因此,您只是将这些行按原样转换为 JSON,这会生成您看到的 JSON 字符串值的平面列表.

要解决这个问题,您必须自己将文本文件解析为结构化对象(哈希表),逐块地将它们传递给 ConvertTo-Json:

# 将输入文件整体读取(-Raw)并拆分成块(段落)(Get-Content -Raw C:\scripts\file.txt) -split '\r?\n\r?\n' -ne '' |ForEach-Object { # 处理每个块# 为这个块中的键值对初始化一个有序的哈希表.$oht = [有序] @{}# 遍历块的行.foreach ($line in $_ -split '\r?\n' -ne '') {# 将行拆分为键和值...$key, $val = $line -split ':', 2# ... 并将它们添加到哈希表中.$oht[$key.Trim()] = $val.Trim()}$oht # 输出哈希表.} |ConvertTo-Json

以上产生了所需的输出.

<小时>

顺便说一句:

<块引用>

没有这部分:
%{$_.PSObject.BaseObject}
它只是深入到可能需要很长时间的对象树中.

问题在于 Get-Content 用额外的、通常不可见的属性来修饰它输出的行,这些属性提供源信息,例如读取行的文件路径.

这些通常隐藏的属性在序列化场景中意外出现,例如使用 ConvertTo-Json 时.

上面的解决方案隐式地绕过了这个问题,因为在处理过程中正在创建字符串.

虽然附加属性可能有用,但它们通常不仅不需要,而且会降低 Get-Content 的速度.

  • 这个 GitHub issue 建议添加一个开关到 Get-允许选择退出装饰行的内容(从 PowerShell Core 7.0.0-preview.3 开始未实现)

  • 作为补充,这个 GitHub 问题建议将 PowerShell 添加的属性忽略与原始 JSON 类型对应的类型,包括 [string](从 PowerShell Core 7.0.0-preview.3 开始未实现)

I am trying to convert a text file to a JSON-formatted string, but the double-quotation marks are not correctly positioned.

My file.txt contains the following structured information (two empty lines at the beginning as well):

adapter_name : empty1 route_age : 10 route_nexthop : 172.0.0.1 route_protocol : NETMGMT1 speed : null

adapter_name : empty2 route_age : 100 route_nexthop : 172.0.0.2 route_protocol : NETMGMT2 speed : null

adapter_name : empty3 route_age : 1000 route_nexthop : 172.0.0.3 route_protocol : NETMGMT3 speed : null

My code is:

$data = Get-Content C:\scripts\file.txt | %{$_.PSObject.BaseObject}
$data | ConvertTo-Json 

Without this part:

%{$_.PSObject.BaseObject}

It's just descending very deeply into the object tree which could take a long time.

The actual result is:


    [
        "",
        "",
        "adapter_name          : empty1",
        "route_age             : 10",
        "route_nexthop         : 172.0.0.1",
        "route_protocol        : NETMGMT1",
        "speed                 : null "
        "",
        "adapter_name          : empty2",
        "route_age             : 100",
        "route_nexthop         : 172.0.0.2",
        "route_protocol        : NETMGMT2",
        "speed                 : null "
        "",
        "adapter_name          : empty3",
        "route_age             : 1000",
        "route_nexthop         : 172.0.0.3",
        "route_protocol        : NETMGMT3",
        "speed                 : null "
    ]

And the expected result is:

[
  {
    "adapter_name"         : "empty1",
    "route_age"            : 10,
    "route_nexthop"        : "172.0.0.1",
    "route_protocol"       : "NETMGMT1",
    "speed"                : null
  },
  {
    "adapter_name"         : "empty2",
    "route_age"            : 100,
    "route_nexthop"        : "172.0.0.2",
    "route_protocol"       : "NETMGMT2",
    "speed"                : null
  },
  {
    "adapter_name"         : "empty3",
    "route_age"            : 1000,
    "route_nexthop"        : "172.0.0.3",
    "route_protocol"       : "NETMGMT3",
    "speed"                : null
  }
]

The examples 4 and 5 in the link https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-6 show how to use the cmdlet ConvertoTo-Json with a similar situation, but without problems.

解决方案

Get-Content merely returns the individual lines from a text file, it knows nothing about any structure that may be encoded in those lines.

Therefore, you're just converting the lines as-is to JSON, which results in the flat list of JSON string values you're seeing.

To fix that problem, you must perform your own parsing of the text file into structured objects (hash tables), block by block, and pass those to ConvertTo-Json:

# Read the input file as a whole (-Raw) and split it into blocks (paragraphs)
(Get-Content -Raw C:\scripts\file.txt) -split '\r?\n\r?\n' -ne '' |
  ForEach-Object { # Process each block
    # Initialize an ordered hashtable for the key-values pairs in this block.
    $oht = [ordered] @{}
    # Loop over the block's lines.
    foreach ($line in $_ -split '\r?\n' -ne '') {
      # Split the line into key and value...
      $key, $val = $line -split ':', 2
      # ... and add them to the hashtable.
      $oht[$key.Trim()] = $val.Trim()
    }
    $oht # Output the hashtable.
  } | ConvertTo-Json

The above yields the desired output.


As an aside, re:

Without this part:
%{$_.PSObject.BaseObject}
It's just descending very deeply into the object tree which could take a long time.

The issue is that Get-Content decorates the lines it outputs with additional, normally invisibly properties that provide origin information, such as the path of the file the lines were read from.

These normally hidden properties surface unexpectedly in serialization scenarios, such as when ConvertTo-Json is used.

The solution above implicitly bypasses this problem, because new strings are being created during processing.

While the additional properties can be useful, they're frequently not only not needed, but also slow Get-Content down.

  • This GitHub issue proposes adding a switch to Get-Content that allows opting out of having the lines decorated (not implemented as of PowerShell Core 7.0.0-preview.3)

  • Complementarily, this GitHub issue proposes that PowerShell-added properties be ignored for types that correspond to primitive JSON types, which includes [string] (not implemented as of PowerShell Core 7.0.0-preview.3)

这篇关于带有双引号的 Powershell ConvertTo-Json 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆