我正在尝试在此脚本中使用$a
变量来处理中间步骤,以便我不必反复使用$array[$array.Count-1]
。同样适用于$prop
。但是,循环中的最后一个值会覆盖值。
$guests = Import-Csv -Path C:\Users\shant_000\Desktop\UploadGuest_test.csv
$output = gc '.\Sample Json.json' | ConvertFrom-Json
$array = New-Object System.Collections.ArrayList;
foreach ($g in $guests) {
$array.Add($output);
$a = $array[$array.Count-1];
$a.Username = $g.'EmailAddress';
$a.DisplayName = $g.'FirstName' + ' ' + $g.'LastName';
$a.Password = $g.'LastName' + '123';
$a.Email = $g.'EmailAddress';
foreach ($i in $a.ProfileProperties.Count) {
$j = $i - 1;
$prop = $a.ProfileProperties[$j];
if ($prop.PropertyName -eq "FirstName") {
$prop.PropertyValue = $g.'FirstName';
} elseif ($prop.PropertyName -eq "LastName") {
$prop.PropertyValue = $g.'LastName';
}
$a.ProfileProperties[$j] = $prop;
}
$array[$array.Count-1] = $a;
}
$array;
答案 0 :(得分:0)
所有数组元素都引用一个实际变量:$output
。
每次重复JSON解析创建一个全新的对象:
$jsontext = gc '.\Sample Json.json'
..........
foreach ($g in $guests) {
$a = $jsontext | ConvertFrom-Json
# process $a
# ............
$array.Add($a) >$null
}
如果JSON文件非常大并且您只更改了其中的一小部分,则可以通过.PSObject.Copy()
对更改的部分(及其整个父链)使用更快的克隆技术:
foreach ($g in $guests) {
$a = $output.PSObject.Copy()
# ............
$a.ProfileProperties = $a.ProfileProperties.PSObject.Copy()
# ............
foreach ($i in $a.ProfileProperties.Count) {
# ............
$prop = $a.ProfileProperties[$j].PSObject.Copy();
# ............
}
$array.Add($a) >$null
}
答案 1 :(得分:0)
正如其他人所指出的那样,追加$object
会附加对同一个对象的引用,因此您不断更改列表中所有元素的值。不幸的是,如果您的JSON数据结构具有嵌套对象,那么@wOxxOm建议的方法(我认为最初也会起作用)也不起作用,因为Copy()
只克隆最顶层的对象而嵌套对象仍然是引用他们原来的。
演示:
PS C:\> $o = '{"foo":{"bar":42},"baz":23}' | ConvertFrom-Json PS C:\> $o | Format-Custom * class PSCustomObject { foo = class PSCustomObject { bar = 42 } baz = 23 } PS C:\> $o1 = $o PS C:\> $o2 = $o.PSObject.Copy()
如果更改bar
和$o1
上的嵌套属性$o2
,则它在两个对象上都包含上次设置为其中任何一个的值:
PS C:\> $o1.foo.bar = 23 PS C:\> $o2.foo.bar = 24 PS C:\> $o1.foo.bar 24 PS C:\> $o2.foo.bar 24
只有更改了最顶层对象的属性,才会在$o1
和$o2
之间产生差异:
PS C:\> $o1.baz = 5 PS C:\> $o.baz 5 PS C:\> $o1.baz 5 PS C:\> $o2.baz 23
虽然你可以做deep copy,但它并不像人们想象的那么简单明了。通常,在您的问题的评论中建议的@PetSerAl多次创建对象需要花费更少的精力(和更简单的代码)。
我还建议避免在循环中追加数组(或arraylist)。您可以简单地在循环内回显对象,并通过将循环分配给变量来将整个输出收集为列表/数组:
$json = Get-Content '.\Sample Json.json' -Raw
$array = foreach ($g in $guests) {
$a = $json | ConvertFrom-Json # create new object
$a.Username = $g.'EmailAddress'
...
$a # echo object, so it can be collected in $array
}
在PowerShell v3和更新版本(或早期版本的Get-Content -Raw
)上使用Get-Content | Out-String
以避免JSON文件中的多行JSON数据出现问题。