我有一个PowerShell脚本,其目标是将传入的JSON对象转换为不同类型的JSON对象。("为什么"不在这个问题的范围之内。)脚本(到目前为止)如下(URL被混淆了,不能工作):
function Map-TempStudents {
param($uffStudent) # JObject containing UFF-formatted student
[String]$districtCode = $uffStudent.Item("DistrictCode").ToString()
Write-Host "districtCode = " $districtCode
$tempStudent = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$tempStudent.Add("DistrictNum", $uffStudent.Item("DistrictCode").ToString())
Write-Host "tempStudent(DistrictNum) = " $tempStudent.Item("DistrictNum").ToString()
}
$currentPath = Split-Path -parent $MyInvocation.MyCommand.Definition
$jsonNetPath = $currentPath + 'Newtonsoft.Json.dll'
Add-Type -Path $jsonNetPath
$wc = New-Object system.Net.WebClient;
$studentPersonal = $wc.downloadString("http://test.foo.org/StudentPersonal")
$json = [Newtonsoft.Json.Linq.JObject]::Parse($studentPersonal)
$studentPersonal | Out-File "test.txt" # DEBUG
$studentBases = $json.Item("Data").Item("AssignTeacher")
Map-TempStudents -uffStudent $studentBases[0]
运行此脚本将得到以下输出:
districtCode = 0745
tempStudent(DistrictNum) = 485
需要说明的是,"0745"是正确值,"485"是意外值。
我希望tempStudent(distritnum)也为"0745"。
为什么这个值会这样改变?
我能够用以下脚本重现您的问题(假设Newtonsoft.Json.dll已经加载到PowerShell中):
$jo = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$jo.Add("foo", "0745")
Write-Host $jo.Item("foo").ToString()
JObject
上的Add
方法接受object
作为它的第二个参数。如果传递一个以零为前导的数字字符串(并且所有数字都小于8),则将其解释为八进制数。因此"0745"被转换成"485"。这一定是PowerShell的东西,因为c#中的等效代码可以正常工作:
JObject jo = new JObject();
jo.Add("foo", "0745");
Console.WriteLine(jo["foo"].ToString());
为了防止在PowerShell中不必要的转换,在将字符串传递给JObject.Add()
之前将其包装在JValue
中,例如:
$jval = New-Object -TypeName Newtonsoft.Json.Linq.JValue -ArgumentList "0745"
$jo.Add("foo", $jval)
以下是Map-TempStudents
函数的修正:
function Map-TempStudents {
param($uffStudent) # JObject containing UFF-formatted student
$districtCode = New-Object -TypeName Newtonsoft.Json.Linq.JValue -ArgumentList $uffStudent.Item("DistrictCode").ToString()
Write-Host "districtCode = " $districtCode.ToString()
$tempStudent = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$tempStudent.Add("DistrictNum", $districtCode)
Write-Host "tempStudent(DistrictNum) = " $tempStudent.Item("DistrictNum").ToString()
}