【问题标题】:Trying to convert CSV into a particular JSON format尝试将 CSV 转换为特定的 JSON 格式
【发布时间】:2020-11-06 17:53:59
【问题描述】:

我需要将 CSV 转换为特定的 JSON 格式,但遇到了问题。

我目前创建了以下 powershell 代码,该代码采用 CSV 文件,其中包含多列和每列的数据

enter code here $csvcontent = get-content "C:\tmp\vmfile.csv" | select -Skip 1
$Json =foreach($line in $csvcontent){

$obj = [PSCustomObject]@{
    description = ($line -split ",")[0] -replace "`""
    requestedFor = ($line -split ",")[1] -replace "`""
    VMs = @{
    vmType = $(($line -split ",")[5] -replace "`"");
    environment = $(($line -split ",")[6] -replace "`"");
    vmdescription = $(($line -split ",")[7] -replace "`"");
    function = $(($line -split ",")[8] -replace "`"");
    datacenter = $(($line -split ",")[9] -replace "`"");
    Size = $(($line -split ",")[10] -replace "`"");
    adDomain = $(($line -split ",")[11] -replace "`"");
    Hostname = $(($line -split ",")[12] -replace "`"")
    }
    ExtraDisks = @{
    VolumeName = $(($line -split ",")[14] -replace "`"");
    VolumeLetter = $(($line -split ",")[15] -replace "`"");
    Size = $(($line -split ",")[16] -replace "`"")
    }
}

$obj | ConvertTo-Json

} 

$json -replace '(?<=:\s+){','[ {' -replace '(?<="\s+)}','} ]'

然后生成以下 json 文件,这不是我需要的,因为我希望它全部位于 VM 括号下,每个 VM 都没有单独的括号

enter code here

{
"requestedFor":  "John Doe",
"VMs":  {
            "Size":  "Medium",
            "datacenter":  "DC1",
            "environment":  "dev",
            "adDomain":  "mydomain.com",
            "vmType":  "Windows Server",
            "vmdescription":  "VM Build1",
            "function":  "app",
            "Hostname":  "VMBuild1"
        },
"ExtraDisks":  {
                   "VolumeLetter":  "G",
                   "Size":  "10",
                   "VolumeName":  "Logs"
               }
  }
 {
   "requestedFor":  "John Doe",
   "VMs":  {
            "Size":  "Medium",
            "datacenter":  "DC2",
            "environment":  "prod",
            "adDomain":  "mydomain.com",
            "vmType":  "Windows Server",
            "vmdescription":  "VM Build2",
            "function":  "app",
            "Hostname":  "VMBuild2"
        },
"ExtraDisks":  {
                   "VolumeLetter":  "E",
                   "Size":  "50",
                   "VolumeName":  "Data"
               }

}

但我需要它看起来像这样

enter code here 
{
"requestedFor":  "John Doe",
"VMs": [ {
    "vmType": "Windows Server",
    "environment": "dev",
    "description":  "VMBuild1",
    "function": "app",
    "datacenter": "DC1",
    "size": "Medium",
    "adDomain": "mydomain.com",
    "Hostname": "VMBuild1",
            "ExtraDisks": [ {
        "VolumeName": "Logs",
        "VolumeLetter": "G",
        "VolumeSize": 10
        }
    ]
    },
    {
    "vmType": "Windows Server",
    "environment": "prod",
    "description":  "VMBuild2",
    "function": "app",
    "datacenter": "DC2",
    "size": "Medium",
    "adDomain": "mydomain.com",
    "Hostname": "VMBuild2",
            "ExtraDisks": [ {
        "VolumeName": "Data",
        "VolumeLetter": "E",
        "VolumeSize": 50
        }
    ]
    }
    ]
    }

这是 CSV 文件的内容

     vmType environment description function    datacenter  Size    adDomain    Hostname    VolumeName  VolumeLetter    VolumeSize
     Windows Server dev VMBuild1    app DC1 Medium  mydomain.com    VMBUILD1    Logs    G   10
     Windows Server prod    VMBuild2    app DC2 Medium  mydomain.com    VMBUILD2    Data    E   50

【问题讨论】:

  • 为什么不先使用 import-csv?
  • 请向我们展示C:\tmp\vmfile.csv 原样的前 3 或 4 行。这意味着在记事本中打开它,复制前几行并将其粘贴到您的问题中作为Formatted 文本。
  • @Theo,感谢您的回复,我已将 CSV 内容添加到原始问题中
  • 请问您能否将此 csv 示例添加为文本而不是图像?
  • @Theo,很抱歉现在已经完成了

标签: json powershell csv


【解决方案1】:

虽然您的示例 CSV 没有显示(从 Excel 复制/粘贴),但我假设它在记事本中打开时看起来像这样:

"vmType","environment","description","function","datacenter","Size","adDomain","Hostname","VolumeName","VolumeLetter","VolumeSize" "Windows Server","dev","VMBuild1","app","DC1","Medium","mydomain.com","VMBUILD1","Logs","G","10" "Windows Server","prod","VMBuild2","app","DC2","Medium","mydomain.com","VMBUILD2","Data","E","50" "Windows Server","dev","VMBuild1","app","DC1","Medium","mydomain.com","VMBUILD1","Scripts","H","25"

CSV 没有RequestedFor 的列,因此下面的代码将其用作硬编码变量。

您需要使用Import-Csv,而不是将csv读取为字符串数组并进行大量拆分和删除引号字符。

在那之后,唯一剩下要做的就是您希望最终 JSON 格式的方式。

$requestor = 'John Doe'
$csvData   = Import-Csv -Path 'D:\Test\vmfile.csv'

# get an array of PSObjects
# we use 'Group-Object Hostname' here to allow VMs with multiple extra disks
$allVMs = $csvData | Group-Object Hostname | ForEach-Object {
    $disks = $_.Group | Select-Object VolumeName, VolumeLetter, VolumeSize
    $vm = $_.Group[0] | Select-Object * -ExcludeProperty VolumeName, VolumeLetter, VolumeSize
    $vm | Add-Member -MemberType NoteProperty -Name 'ExtraDisks' -Value @($disks)
    # output the VM object
    $vm
}

# combine the requestor, main element 'VMs' and the objects 
# gathered above into a new object and convert that to JSON
[PsCustomObject]@{
    RequestedFor = $requestor
    VMs          = @($allVMs)
} | ConvertTo-Json -Depth 4

输出:

{
    "RequestedFor":  "John Doe",
    "VMs":  [
                {
                    "vmType":  "Windows Server",
                    "environment":  "dev",
                    "description":  "VMBuild1",
                    "function":  "app",
                    "datacenter":  "DC1",
                    "Size":  "Medium",
                    "adDomain":  "mydomain.com",
                    "Hostname":  "VMBUILD1",
                    "ExtraDisks":  [
                                       {
                                           "VolumeName":  "Logs",
                                           "VolumeLetter":  "G",
                                           "VolumeSize":  "10"
                                       },
                                       {
                                           "VolumeName":  "Scripts",
                                           "VolumeLetter":  "H",
                                           "VolumeSize":  "25"
                                       }
                                   ]
                },
                {
                    "vmType":  "Windows Server",
                    "environment":  "prod",
                    "description":  "VMBuild2",
                    "function":  "app",
                    "datacenter":  "DC2",
                    "Size":  "Medium",
                    "adDomain":  "mydomain.com",
                    "Hostname":  "VMBUILD2",
                    "ExtraDisks":  [
                                       {
                                           "VolumeName":  "Data",
                                           "VolumeLetter":  "E",
                                           "VolumeSize":  "50"
                                       }
                                   ]
                }
            ]
}

当然,您可以将其保存在 json 文件中,方法是在其上附加 | Set-Content -Path 'TheOutputFile.json'

附: PowerShell 不会产生“漂亮”的 json。如果您需要将其转换为适当间隔的 json,请参阅我的函数 Format-Json

【讨论】:

  • 谢谢@Theo,这正是我所需要的
【解决方案2】:

您不需要自己解析 csv。 这就是 ConvertFrom-Csv / Import-CSV 的用途。

这就是我的做法。

$CSVObj = get-content "C:\tmp\vmfile.csv" -Raw | ConvertFrom-Csv
$CSVObj | ConvertTo-Json | Set-Content "C:\tmp\vmfile.json"

就是这样!

但让我们更进一步。您的问题中没有 CSV 样本,因此人们可能会认为输出 JSON 可能仍然不正确。您将如何确保获得您想要的格式?

通过从导入的对象创建一个全新的对象结构,然后将其导出。

这是一个简单的表达方式。


$CSVObj = get-content "C:\tmp\vmfile.csv" -Raw | ConvertFrom-Csv

# Create a new object from $csvObj that you will then export to csv
$Output = foreach ($item in $CSVObj) {
    [PSCustomObject]@{
        Requester = $item.requestedFor
        VMs       = $item.VMs
        Count     = $item.VMs.Count
    }
}

$output | ConvertTo-Json | Set-Content "C:\tmp\vmfile.json"

您将成功修改要输出的 json 以满足您的需求。

【讨论】:

  • 嗨 Sage,感谢您的回复,我已经上传了我使用的 csv link。我运行您的代码的输出没有为我提供代码“VM”之间的每一行上的所有 VM:[ {
  • 请看图片显示输出link。正如您所看到的,每个虚拟机都会启动一个新的虚拟机”:[{。我需要所有虚拟机都归于一个
猜你喜欢
  • 1970-01-01
  • 2019-02-01
  • 2016-02-12
  • 2021-10-29
  • 1970-01-01
  • 2016-11-06
  • 2015-03-26
  • 1970-01-01
相关资源
最近更新 更多