使用Powershell从Json结构提取值时出现问题

时间:2019-03-04 05:13:48

标签: json powershell

使用Powershell,我将一个JSON代码片段返回到我的第一个变量中(这总是可以正常工作);

# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'

然后我将convert函数调用为这样的临时变量;

$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;

这会将Json放入一个漂亮的小数据结构中;

         message_id
         ----------
9093813071099257562

通过调用它可以从中选择所需的值;

$nMessage_id = $ResponseBody.message_id;

通常,这可以正常工作,我将值放入第二个变量;

$nMessage_id = 9093813071099257562

问题是:有时即使 $ whatStatusJsonContent 确实记录为Json从函数正确返回,但在 $ nMessage_id 中却什么也没得到。

我的问题是:我必须 ConvertFrom-Json ,还是可以从First变量中原始读取它?

组合解决方案:感谢@mklement()和@ Bernard-Moeskops

# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'

$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;

if($ResponseBody.message_id){
    # ConvertFrom-Json got the value!
    $nMessage_id = $ResponseBody.message_id
}else{
    # ConvertFrom-Json didn't work!
    $nMessage_id = = ($whatStatusJsonContent -split '[:}]')[1]
}

2 个答案:

答案 0 :(得分:2)

您的代码没有任何明显的错误。

ConvertFrom-Json应该可以正常工作,并返回具有[pscustomobject]属性的.message_id实例。

在您的示例中,message_id JSON属性值是一个 number ,它是一个整数,为此ConvertTo-Json自动选择合适的整数数据类型,如下所示:最小可以容纳值的签名类型> = [int]System.Int32 [1] [int]-> [long]System.Int64 )-> [decimal]System.Decimal));需要注意的是,如果该值甚至无法容纳[decimal],则使用-不精确-[double] [2]

在问题中带有示例JSON的情况下,选择了[long]

在后续评论中,您声明:

  

该例程每小时进行1000次呼叫,对于大多数Json而言,Json会回来,并且$nMessage_id的产生效果非常好。然后,突然间$nMessage_id为空,即使Json被记录为恢复正常也是如此。因此,在ConvertFrom-Json$ResponseBody.message_id中的某个位置值会丢失...

我没有任何解释,但是如果出于某种原因-ConvertFrom-Json是罪魁祸首,您可以尝试字符串操作作为解决方法 < / strong>提取消息ID,看看是否有帮助:

$whatStatusJsonContent = '{"message_id":9093813071099257562}'

# Extract the message_id property value as a *string*  
# (which you can cast to a numeric type if/as needed).  
$message_id = ($whatStatusJsonContent -split '[:}]')[1]

上面的代码在9093813071099257562中存储了一个内容为$message_id的字符串;请注意,按照书面要求,输入字符串必须具有与上述空格相同的确切格式;尽管可以使文本解析更加健壮,但不必担心格式变化是使用专用解析器(例如ConvertFrom-Json)的一个很好的理由。


另一种选择是尝试不同的 JSON解析器,以查看是否有帮助。 Json.NET是.NET世界中杰出的JSON解析器(现在是PowerShell Core 中JSON cmdlet的基础):

$whatStatusJsonContent = '{"message_id":9093813071099257562}'

$message_id = [NewtonSoft.Json.Linq.JObject]::Parse($whatStatusJsonContent).message_id.Value

注意:Json.NET-如PowerShell _Core中的ConvetFrom-Json-值得推荐的是,一旦数字太大而无法容纳[bigint]时,也可以使用任意大的[long]类型。

ConvertFrom-Json cmdlet相比,使用Json.NET程序集还具有更好的性能的优势。

在PowerShell Core 中,您可以按原样运行以上代码(程序集已预加载);在Windows PowerShell中,您必须通过上面的链接下载程序包,并将程序集(NewtonSoft.Json.dll)添加到使用Add-Type -LiteralPath的会话中。


[1]奇怪的是,在PowerShell Core 中,从(至少)v6.2.0开始,选择的最小类型是[long]System.Int64)。

[2]更有用的是,PowerShell Core 从(至少)v6.2.0开始,创建了一个任意大的[bigint]System.Numerics.BigInteger)实例值不再适合[long];也就是说,[decimal]类型将被完全跳过。

答案 1 :(得分:1)

您将不得不对其进行转换,以便PowerShell可以理解它。它将从字符串转换为PSCustomObject。只需通过询问变量的类型即可。

$ResponseBody.message_id.GetType()

如果有时输出为空,则可以执行以下操作:

if($ResponseBody.message_id){
    $nMessage_id = $ResponseBody.message_id
}else{
    throw "No message id found"
}

希望这会有所帮助。