如何加载JSON文件并将其转换为特定类型的对象?

59
我有一个类型为 FooObject 的对象,并且我有一个序列化自 FooObject 实例的 JSON 文件。现在我想使用 ConvertFrom-Json 将 JSON 文件加载到内存中,并将命令的输出转换为 FooObject 对象,然后在一个只接受 FooObject 作为参数类型的 cmdlet Set-Bar 中使用新的对象。
但是我发现 ConvertFrom-Json 的输出类型是 PSCustomObject,我没有找到任何将 PSCustomObject 转换为 FooObject 的方法。
3个回答

73
尝试将自定义对象强制转换为 FooObject:
$foo = [FooObject](Get-Content 'C:\path\to\your.json' | Out-String | ConvertFrom-Json)

如果那样不起作用,请尝试使用输入对象的属性构造FooObject实例(前提是类有这样的构造函数):

$json = Get-Content 'C:\path\to\your.json' | Out-String | ConvertFrom-Json
$foo = New-Object FooObject ($json.Foo, $json.Bar, $json.Baz)

如果那个方法也不起作用,您需要创建一个空的FooObject实例,并在之后更新其属性:

$json = Get-Content 'C:\path\to\your.json' | Out-String | ConvertFrom-Json
$foo = New-Object FooObject
$foo.AA = $json.Foo
$foo.BB = $json.Bar
$foo.CC = $json.Baz

由于我拥有 Set-Bar 的代码(使用 C# 编写),是否可能让它接受 PSCustomObject 并在内部将其转换为 FooObject?这对于我的 cmdlet 用户来说哪种方式更好呢? - NonStatic
如果你将接口改为接受 PSCustomObjectObject,应该是可行的。虽然我对C#不太熟悉。 - Ansgar Wiechers
5
您应该使用 Get-Content -Raw 'C:\path\to\your.json' 命令来加载您的 JSON 内容。 - Laymain

17

2
更简短的方式:Get-Content <json文件> | ConvertFrom-Json - Marshal
5
如果没有指定类型,这个程序如何将 JSON 转换为一种 特定 类型? - KUTlime

6

我知道这是一篇旧文章,但我找到了一种更有效的方法来做到这一点,如果强制转换不起作用。首先尝试进行强制转换,只要您的类不包含自定义类型的嵌套集合,那么强制转换将起作用。假设您的类看起来像以下内容。

class Container 
{
    [string] $Id
    [string] $Name
    [System.Collections.Generic.List[Process]] $Processes
}
class Process
{
    [string] $Id
    [string] $Name
}

ConvertFrom-Json将其转换为[PSCustomObject],但会将List [Process]转换为Object [],这将使任何强制转换操作抛出以下异常。

无法将类型为“System.Object []”的“System.Object []”值转换为类型“System.Collections.Generic.List`1 [Process]”。

ConvertToFinalInvalidCastException

请使用以下方法反序列化此类层次结构。

$serializer = [System.Web.Script.Serialization.JavaScriptSerializer]::new()

$content = $serializer.Deserialize((Get-Content -Path $JsonFilePath), [YourCustomType])
[System.Web.Script.Serialization.JavaScriptSerializer]ConvertFrom-Json背后的实现方式。我创建了一个新实例,就能轻松地将一个多层级(确切地说是四个级别,每个级别都有下一级别的集合)的JSON文件转换成我的PowerShell类。我也意识到这可以简化为以下代码,但以上的代码更易读。
$content = [System.Web.Script.Serialization.JavaScriptSerializer]::new().Deserialize((Get-Content -Path $JsonFilePath), [YourCustomType])

1
当尝试使用此方法时,我遇到了以下问题:
无法从程序集'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'中加载类型'System.Web.UI.WebResourceAttribute'。
这是在添加了Add-Type -AssemblyName System.WebAdd-Type -AssemblyName System.Web.Extensions之后发生的。
- Kristian Williams
我不确定 @KristianWilliams。我从来没有在我的会话中添加过类型。如果您可以使用 ConvertFrom-Json,它应该已经可用。就像我在答案中所说的那样,这是 cmdlet 使用的程序集。因此,您不需要添加类型。 - Patrick Mcvay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接