【问题标题】:Trying to Deserialize JSON to typed Object in Powershell尝试将 JSON 反序列化为 Powershell 中的类型化对象
【发布时间】:2021-11-05 02:49:22
【问题描述】:

我正在尝试将 JSON 字符串(来自 API 响应)反序列化为我在 Powershell 中键入的对象,但是,我不断收到两种类型的错误。

我有两个 PowerShell 类,例如:

cpublic class DataType
{
    [string] key
    [string] dataName
}

public class DataTypeList
{
    [string] key 
    [string] name 
    [string] localeKey 
}

public class Event
{
    [string] key
    [string] name
    [string] localeKey
    [DataType] DataType
    [List[DataTypeList]] DataTypeList
}

public class Root
{
   [List[Event]] $events
}

我的 JSON 响应如下所示:

  {
   "Events":[
      {
         "key":"1234",
         "name":"Bob Muprhy",
         "localeKey":"4",
         "DataType":{
            "key":"1111111",
            "dataName":"Name One"
         },
         "DataTypeList":[
            {
               "key":"983984",
               "name":"New name",
               "localeKey":"34985"
            },
            {
               "key":"124543534",
               "name":"New name new Name",
               "localeKey":"asdfsadf"
            }
         ]
      },
      {
         "key":"123456567",
         "name":"Pete big",
         "localeKey":"4",
         "DataType":{
            "key":"1111111",
            "dataName":"Name 1"
         },
         "DataTypeList":[
            {
               "key":"983984",
               "name":"New name",
               "localeKey":"34985"
            },
            {
               "key":"124543534",
               "name":"New name new Name",
               "localeKey":"asdfsadf"
            }
         ]
      }
   ]
}

我的代码目前看起来像这样,我正在使用 Invoke-RestMethod,因为我读到它会自动将 ConvertFrom-JSON 应用于 API 响应/内容

这里我得到了 json 响应:

$json = Invoke-RestMethod -Uri "<API Link>"

在这里,我尝试使用 Cast-Initialization 技术“将 JSON 反序列化到我的对象中”

$response = [Root]($json)

但是我会得到一个错误响应:无法创建“根”类型的对象。无法将类型“System.Object[]”的“System.Object[]”值转换为类型“System.Collections.Generic.List`1[FeaturedEvent]

我也尝试过这样做:

$response = [Root]($json.Events)

但是,这也会返回错误无法将“System.Object[]”类型的“System.Object[]”值转换为“Root”类型

在 C# 中反序列化某些东西时,我知道我可以做类似的事情

*JsonConvert.DeserializeObject<Root>(json);*

尝试在 Powershell 中复制相同的内容

我也试过这个:

 $root = [Root]::new()

 $root.Events = $json.Events

但是我又收到了同样的错误

【问题讨论】:

  • 也许 JSON 响应有 additional 属性超出了 [Event] 类定义的属性?
  • 抱歉忘记在其中提及它们 - 有,但我也为它们创建了额外的类 - 现在会更新
  • @Adam 你能不能也测试一下this 是否有帮助。
  • 尝试得到错误“找不到“反序列化”的重载和参数计数:“2””

标签: powershell


【解决方案1】:

这里是自包含的示例代码,证明您的方法应该有效(将类定义中的语法错误放在一边,下面已更正)。

  • 您问题中的示例 JSON 将通过 ConvertFrom-Json 解析为 [pscustomobject] 对象图,以模拟您的 Invoke-RestMethod 调用。

  • [Root] 的简单转换足以将[pscustomobject] 图转换为基于您的自定义类的强类型对象图。

  • 将结果重新转换为 JSON 以证明数据已正确解析 - 请注意有关属性名称大小写的源代码 cmets。

using namespace System.Collections.Generic

# Your custom classes.
class DataType
{
    [string] $key
    [string] $dataName
}

class DataTypeList
{
    [string] $key 
    [string] $name 
    [string] $localeKey 
}

class Event
{
    [string] $key
    [string] $name
    [string] $localeKey
    [DataType] $DataType
    [List[DataTypeList]] $DataTypeList
}

class Root
{
   [List[Event]] $Events
}

# Simulate an Invoke-RestMethod call that
# returns JSON, which Invoke-RestMethod automatically
# parses into a [pscustomobject] object graph.
$fromJson = ConvertFrom-Json @'
{
  "Events":[
     {
        "key":"1234",
        "name":"Bob Muprhy",
        "localeKey":"4",
        "DataType":{
           "key":"1111111",
           "dataName":"Name One"
        },
        "DataTypeList":[
           {
              "key":"983984",
              "name":"New name",
              "localeKey":"34985"
           },
           {
              "key":"124543534",
              "name":"New name new Name",
              "localeKey":"asdfsadf"
           }
        ]
     },
     {
        "key":"123456567",
        "name":"Pete big",
        "localeKey":"4",
        "DataType":{
           "key":"1111111",
           "dataName":"Name 1"
        },
        "DataTypeList":[
           {
              "key":"983984",
              "name":"New name",
              "localeKey":"34985"
           },
           {
              "key":"124543534",
              "name":"New name new Name",
              "localeKey":"asdfsadf"
           }
        ]
     }
  ]
}
'@

# Parse the [pscustomobject] graph into a strongly
# typed object graph based on the custom classes.
# Note: PowerShell ignores case differences between
#       the property names as specified in the original JSON
#       and the custom-class property names.
$fromJsonStronglyTyped = [Root] $fromJson 

# Reconvert to JSON to demonstrate that roundtripping succeeds.
# Note: The property names are written with the case as defined
#       in your custom classes, which may differ from the original JSON.
$fromJsonStronglyTyped | ConvertTo-Json -Depth 4

【讨论】:

    【解决方案2】:

    您的数据类型有错误。公共类DataTypeList应该只有根据$json有[DataType[]]$DataTypeList。 这应该将您的 json 反序列化为自定义 [Root] 类型:

    class DataType {
        [string]$key;
        [string]$dataName;
    }
    
     class DataTypeList {
        [DataType[]]$DataTypeList;
    }
    
    class Event {
        [string]$key;
        [string]$name;
        [string]$localeKey;
        [DataType]$DataType;
        [Collections.Generic.List[DataTypeList]]$DataTypeList;
    }
    
    class Root {
       [Collections.Generic.List[Event]]$events;
    }
    
    $content = ([System.Web.Script.Serialization.JavaScriptSerializer]::new()).Deserialize($json, [Root])
    

    【讨论】:

      猜你喜欢
      • 2017-12-19
      • 2012-03-06
      • 2019-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多