I'm trying to deserialize a JSON string (which is coming from an API response) into my typed objects in Powershell, however, I keep receiving two types of errors.
I have two PowerShell classes such as:
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
}
and my JSON response looks something like this:
{
"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"
}
]
}
]
}
My code currently looks something like this, I'm using Invoke-RestMethod as I've read up that it will automatically apply the ConvertFrom-JSON to the API response/content
Here i am getting the json response:
$json = Invoke-RestMethod -Uri "<API Link>"
Here I am trying to "deserialize the JSON into my object" by using the Cast-Initialization technique
$response = [Root]($json)
However i will get an error response saying: Cannot create object of type "Root". Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Collections.Generic.List`1[FeaturedEvent]
I tried also to do something like:
$response = [Root]($json.Events)
However, that will also return error Cannot convert the "System.Object[]" value of type "System.Object[]" to type "Root
When deserializing something in C# i know I would be able to do something like
*JsonConvert.DeserializeObject<Root>(json);*
Trying to replica the same here in Powershell
I also did try this:
$root = [Root]::new()
$root.Events = $json.Events
However again I received the same error
CodePudding user response:
Here's self-contained sample code that demonstrates that your approach should work (leaving the syntax errors in the class definitions aside, which have been corrected below).
The sample JSON from your question is parsed into a
[pscustomobject]
object graph viaConvertFrom-Json
, to simulate yourInvoke-RestMethod
call.A simple cast to
[Root]
is sufficient to convert the[pscustomobject]
graph into a strongly typed object graph based on your custom classes.The result is re-converted to JSON to demonstrate that the data was correctly parsed - note the source-code comments regarding case of the property names.
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
CodePudding user response:
Your datatype has an error. public class DataTypeList should have [DataType[]]$DataTypeList only according to $json. this should deserialize your json to custom [Root] type:
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])