【问题标题】:Select-Object Data Failure From Succesful Invoke-RestMethod从成功的 Invoke-RestMethod 中选择对象数据失败
【发布时间】:2019-11-16 21:48:34
【问题描述】:

我有一个使用Invoke-RestMethod -Uri https://... 的休息服务电话。在JSON 中的调用结果可以通过管道将数据传送到Format-Table -Property ... 并显示数据。

但是当Select-Object -Property ... 在调用后使用相同参数时,PSObject 有列但没有数据。如果我使用不同的网络服务,调用将起作用。

什么可能导致PSObject 不显示任何值?


公共休息网络服务的工作示例

Invoke-RestMethod -Uri https://jsonplaceholder.typicode.com/todos/1 |
Select-Object -Property title

结果

@{title=delectus aut autem}

新的失败不同的 API

Invoke-RestMethod -Uri https://cat-fact.herokuapp.com/facts | Select-Object -Property text

【问题讨论】:

  • Select-Object 返回带有空道具的对象的最常见原因是使用了错误的道具名称。所以...检查您的实际道具的名称并使用它们。如果您想更改这些道具名称,请使用计算表达式。
  • 我尝试了第三个公共 API 发送大量数据,但它也失败了......我想知道这是否是更大数据的内部 JSON 解析问题。我已经看到,由于使用了 XML 转换器,SQL Server 数据 sproc 返回了 2033 个字符的挂钩。
  • 您的用户名无法在我的键盘上输入。 [sigh ...] ///// 返回的数据中没有 text 属性。唯一的属性是 all & ,其中包含一个数组,其中包含具有 .text 属性的对象。
  • @Lee_Dailey 哦,我讨厌其他用户在使用@ 标记他们时这样做。对不起。让我看看All 属性。我的初始数据是数组中的子对象。很有趣。
  • 不是一个严重的问题。 [grin] ///// 请看我的回答。它只涵盖了猫的链接,但奥塔的想法在其他地方也适用。 [咧嘴]

标签: json powershell psobject select-object


【解决方案1】:

在转换 JSON 数组时,您偶然发现了两个 PowerShell 怪异的邪恶组合:

  • Invoke-RestMethodConvertFrom-Json 通过管道发送从 JSON 转换而来的数组作为一个整体,而不是像往常一样逐个元素地发送

    • 注意:在 PowerShell (Core) 7.0 中,ComvertFrom-Json 的行为已更改以与通常的枚举保持一致 -元素行为,并添加了 -NoEnumerate 开关作为对旧行为的选择。有关导致此更改的讨论,请参阅GitHub issue #3424

    • 但是,在撰写本文时(PowerShell (Core 7.2) Invoke-RestMethod 仍然表现出这种意外行为,这在GitHub issue #15272 中进行了讨论。

  • Select-Object 不执行member enumeration,因此它直接在数组上查找指定的属性(例如,text),但它不存在。

用一个简单的例子来说明问题

# Windows PowerShell only:
# Because ConvertFrom-Json sends an *array* (of 2 custom objects) through
# the pipeline, Select-Object looks for property .text on the *array* -
# and can't find it.
# The same applies to Invoke-RestMethod (also still in 
# PowerShell (Core) as of v7.2)
PS> ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]' | Select-Object text

text
----
       # NO VALUES 

简单的解决方法是将ConvertFrom-Json / Invoke-RestMethod 调用包含在(...) 中,这强制枚举数组,导致Select-Object 工作正如预期的那样:

# (...) forces enumeration
PS> (ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]') | Select-Object text

text
----
a
b

请注意,诸如Select-Object -Property text(不带-ExpandProperty)之类的命令仍会输出具有.text 属性的自定义对象,而不是.text 属性.

如果你感兴趣的只是属性values,那么解决方法就比较简单了,因为可以直接在数组上使用上面提到的成员枚举: p>

# Using .<propName> on an array (collection) implicitly returns the
# property values from the *elements* of that collection (member enumeration).
PS> (ConvertFrom-Json '[{ "text": "a" }, { "text": "b" }]').text
a
b

注意现在的输出没有text 标头,因为输出的只是字符串值,而不是自定义对象。

【讨论】:

  • 对于我的情况,将Invoke-RestMethod 放在括号中是有效的。我想知道我是否必须调用Invoke-WebRequest 来获取原始json,然后在括号中使用ConvertFrom-Json 进行隐蔽;但幸运的是没有。感谢您的帮助/见解。
【解决方案2】:

您在第二个示例中的问题是没有名为 text 的道具。 [咧嘴一笑]

唯一的道具是all,它包含一个对象数组,其中包含一个名为text的道具。所以你需要一些可以得到更深的道具的东西。一种方法是使用两个Select-Object 调用。像这样的东西......

$Url = 'https://cat-fact.herokuapp.com/facts'
$RawIRM = Invoke-RestMethod -Uri $Url 
$SO_IRM = $RawIRM |
    Select-Object -ExpandProperty all |
    Select-Object -Property text

$SO_IRM 变量现在有一个包含 178 个关于猫的字符串的数组。 [咧嘴一笑]

【讨论】:

  • 我得到了你的答案,为猫取消引用 all 是有意义的。但是我的初始数据在对象数组上没有这样的属性。 [{…}, {…}] 很遗憾,ExpandProperty 不适用于我的数据,例如猫的 all 属性。我确实有能力将 web 服务更改为使用命名属性,但它可能会破坏前端的反应开发人员。感谢您的帮助。
  • @ΩmegaMan - 另一种获取该信息的方法是通过.ForEach() 或其他循环运行它,并使用$_.PropName 引用它。然后,您可以使用各种道具来构建具有您想要的道具的PSCustomObject
  • 您对https://cat-fact.herokuapp.com/facts 调用的分析是正确的(并且很有帮助),但它对于@ΩmegaMan 的问题是偶然的;问题是我们的老朋友github.com/PowerShell/PowerShell/issues/3424
  • @mklement0 - 啊哈! [grin] 这是有道理的......而且相当怪异。谢谢你的信息!
  • 将答案移至 mklement;对不起。但是你帮助我克服了最初的困难,为此……谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多