【powershell】解决数组只有一个元素时转Json变成了对象的问题

通过此方法可以将powershell中只有一个元素的数组转换成json后仍然保持数组输出。

【powershell】解决数组只有一个元素时转Json变成了对象的问题

By img Microanswer Create at:Apr 3, 2025, 4:15:37 PM 

Tags: powershell ContertTo-Json

通过此方法可以将powershell中只有一个元素的数组转换成json后仍然保持数组输出。


事情的起因是一开始我们有个功能是获取Windows中的所有磁盘列表,也就是【此电脑】里展示的那些盘。我们是通过wmic来实现的信息获取,命令如下:

wmic logicaldisk get Caption,FreeSpace,Size,VolumeSerialNumber,Description  /format:list

运行命令可以得到输出:

Caption=C:
Description=本地固定磁盘
FreeSpace=113127522304
Size=214765137920
VolumeSerialNumber=733C9DDF


Caption=D:
Description=本地固定磁盘
FreeSpace=27744464896
Size=285236793344
VolumeSerialNumber=9A1DD4DB

但是后来,Window11下已经开始默认移除 wmic 这个组件了,意味着我们的应用中不能再使用wmic这个命令了。。。(微软说:wmic好用哇?好用那就干掉...)

一、使用 Get-PSDrive 获取磁盘列表

考虑到未来wmic会完全从windows中移除,因此我们现在不再通过wmic获取了,而是通过命令Get-PSDrive来获取。 命令如下:

get-psdrive -psprovider filesystem | select-object name,used,free | ConvertTo-Json

在Powershell中执行命令可以得到输出:

[
    {
        "Name":  "C",
        "Used":  101637824512,
        "Free":  113127313408
    },
    {
        "Name":  "D",
        "Used":  257558593536,
        "Free":  27678199808
    }
]

这样,我们就一样的也拿到了磁盘列表。但是这个命令有个问题,看下面。

二、ConvertTo-Json 转换问题

在 powershell 中,ConvertTo-Json 命令有一个很奇特的设定,就是如果你要转换的数据是只有一个元素的数组,那么转换出来的json结果中会直接帮你把这个元素提取出来然后进行转换。原本的数据是数组,这样一来就变成了另外一种数据类型了,在程序中我们一般不希望这样的事情发生。

举个例子:

# 创建一个字符串数组
$testarr1 = @("str1", "str2")

# 将字符串数组转化为JSON
$testarr1 | ConvertTo-Json

# 得到正确的 JSON 数组。
[
    "str1",
    "str2"
]

上面这个例子中,数组里包含1条以上的数据,转换正常。再看下面的数组只有一条数据时:

# 创建一个字符串数组,只有一个元素
$testarr2 = @("value1")

# 将字符串数组转化为JSON
$testarr2 | ConvertTo-Json

# 得到一个字符串数据,而不是JSON 数组
"value1"

很离谱,这这这....这个特性就会导致我们获取磁盘列表数据时出现问题,当用户电脑里只有一个盘时,我们的命令得到的结果就是一个对象,而不是数组,导致数据解析会出问题。

三、保证 ConvertTo-Json 转换结果统一

要实现 ConvertTo-Json 命令的转换行为总是统一的,有一个十分简便的解决方法,只需要在数组前面加一个,逗号。

例如:

# 在最前面添加一个 , 逗号
,$testarr1 | ConvertTo-Json
{
    "value":  [
                  "str1",
                  "str2"
              ],
    "Count":  2
}

# 对于只有一条数据的数组,也可以。
,$testarr2 | ConvertTo-Json
{
    "value":  [
                  "value1"
              ],
    "Count":  1
}

可以看到,我们的结果中虽然多了几个别的字段,但是我们最终需要的数据都准确的呈现在了 "value" 属性下面。 我们只需要取 value 节点下面的数据即可。

现在我们有了修复方法,针对最开始我的实际业务场景就可以采用下面的代码进行修复了:

,@(get-psdrive -psprovider filesystem | select-object name,used,free) | ConvertTo-Json

在只有一个盘的电脑上运行时,就会得到输出:

{
    "value":  [
                  {
                      "Name":  "C",
                      "Used":  101640720384,
                      "Free":  113124417536
                  }
              ],
    "Count":  1
}

!!完美~

Full text complete, Reproduction please indicate the source. Help you? Not as good as one:
Comment(Comments need to be logged in. You are not logged in.)
You need to log in before you can comment.

Comments (0 Comments)