Always count property as array (JSON convert failure)

Tagged: , , ,

This topic contains 4 replies, has 3 voices, and was last updated by  Martin Nielsen 2 years, 5 months ago.

  • Author
    Posts
  • #24187

    Stig Sörnsen
    Participant

    Hi,

    I have a problem converting some data to JSON because some objects have array properties while other only have a single property.

    Let me try illustrate the problem:

    # Object with object-array property inside
    $customProp = @()
    $customProp += New-Object psobject -Property @{ Name="Test1"; Size="100"}
    $customProp += New-Object psobject -Property @{ Name="Test2"; Size="100"}
    
    $object1 = New-Object psobject -Property @{ Name="Object1"; Something="Weird"}
    $final1 = $object1 | Select-Object Name, Something, @{n="Custom";e={$customProp}}
    
    
    # Object with object property inside
    $customProp = @()
    $customProp += New-Object psobject -Property @{ Name="Test10"; Size="200"}
    
    
    $object2 = New-Object psobject -Property @{ Name="Object2"; Something="Strange"}
    $final2 = $object2 | Select-Object Name, Something, @{n="Custom";e={$customProp}}
    
    
    $list = @()
    $list += $final1
    $list += $final2
    $list

    The output of the above should be:

    Name    Something Custom                                            
    ----    --------- ------                                            
    Object1 Weird     {@{Name=Test1; Size=100}, @{Name=Test2; Size=100}}
    Object2 Strange   @{Name=Test10; Size=200}                          
    

    And the problem is showing already here. Object1's Custom property has and extra set of {} around its content while Object2 is lacking those.
    Resulting converting it to JSON:

    $list | ConvertTo-Json -Depth 3

    [
        {
            "Name":  "Object1",
            "Something":  "Weird",
            "Custom":  {
                           "value":  [
                                         {
                                             "Name":  "Test1",
                                             "Size":  "100"
                                         },
                                         {
                                             "Name":  "Test2",
                                             "Size":  "100"
                                         }
                                     ],
                           "Count":  2
                       }
        },
        {
            "Name":  "Object2",
            "Something":  "Strange",
            "Custom":  {
                           "Name":  "Test10",
                           "Size":  "200"
                       }
        }
    ]
    

    I really need to have it to be same like this:

    [
        {
            "Name":  "Object1",
            "Something":  "Weird",
            "Custom":  [
                                         {
                                             "Name":  "Test1",
                                             "Size":  "100"
                                         },
                                         {
                                             "Name":  "Test2",
                                             "Size":  "100"
                                         }
                                     ]
    
                       
        },
        {
            "Name":  "Object2",
            "Something":  "Strange",
            "Custom":  [
    			{
                           		"Name":  "Test10",
                           		"Size":  "200"
                       	}
    		]
        }
    ]
    

    I need to generate a C# Class from it like this:

    public class Custom
    {
        public string Name { get; set; }
        public string Size { get; set; }
    }
    
    public class RootObject
    {
        public string Name { get; set; }
        public string Something { get; set; }
        public List Custom { get; set; }
    }
    

    Right now json2charp.com gives me classes like this, which I do not fancy 🙂

    public class Value
    {
        public string Name { get; set; }
        public string Size { get; set; }
    }
    
    public class Custom
    {
        public List value { get; set; }
        public int Count { get; set; }
        public string Name { get; set; }
        public string Size { get; set; }
    }
    
    public class RootObject
    {
        public string Name { get; set; }
        public string Something { get; set; }
        public Custom Custom { get; set; }
    }
    

    Any help?

  • #24188

    Stig Sörnsen
    Participant

    I have temporarily overcome this by initializing the $CustomProp array wtih $null ($CustomProp = @($null)) and then do what is necessary with regex afterwards:

    -replace '"Custom":{"value":\[null,', '"Custom":[' -replace '\],"Count":\d},', '],'

    If anyone could tell how to do it properly I would still be very glad 🙂

  • #24194

    Dave Wyatt
    Moderator

    There's a lot going on in the code where you're initializing your objects. When I changed it to this the JSON output matched what you're looking for:

    $list = @(
        [pscustomobject] @{
            Name = 'Object1'
            Something = 'Weird'
            Custom = @(
                [pscustomobject] @{
                    Name = 'Test1'
                    Size = '100'
                }
    
                [pscustomobject] @{
                    Name = 'Test2'
                    Size = '100'
                }
            )
        }
    
        [pscustomobject] @{
            Name = 'Object2'
            Something = 'Strange'
            Custom = @(
                [pscustomobject] @{
                    Name = 'Test10'
                    Size = '200'
                }
            )
        }
    )
    
    $list | ConvertTo-Json -Depth 3
    
  • #24195

    Dave Wyatt
    Moderator

    Figuring out they 'why' of your original output is a little trickier. You used the @() operator to force your $customProp variables to be arrays, but then you put those variables into an Expression script block of Select-Object, which will unroll the single-element array. (Which is why you see it as a single object when looking at both $list and the JSON conversion in the original output.)

    As for that Value and Count bit in your original output? I have no idea where those are coming from. Could be that you've found some bug in the JSON converter, but I'm not seeing it at the moment.

  • #24196

    Martin Nielsen
    Participant

    Well I'm not sure why exactly you're doing the Select-Object thing, but if you initialize the objects using the custom property, then it works.

    $customProp = @()
    $customProp += New-Object psobject -Property @{ Name="Test1"; Size="100"}
    $customProp += New-Object psobject -Property @{ Name="Test2"; Size="100"}
    $object1 = New-Object psobject -Property @{ Name="Object1"; Something="Weird"; Custom = $customProp }
     
    # Object with object property inside
    $customProp = @()
    $customProp += New-Object psobject -Property @{ Name="Test10"; Size="200"}
    $object2 = New-Object psobject -Property @{ Name="Object2"; Something="Strange"; Custom = $customProp }
    
    PS C:\Users\mni> $object1
    
    Custom                                                                                Name                                                                                  Something                                                                            
    ------                                                                                ----                                                                                  ---------                                                                            
    {@{Name=Test1; Size=100}, @{Name=Test2; Size=100}}                                    Object1                                                                               Weird                                                                                
    
    
    PS C:\Users\mni> $object2
    
    Custom                                                                                Name                                                                                  Something                                                                            
    ------                                                                                ----                                                                                  ---------                                                                            
    {@{Name=Test10; Size=200}}                                                            Object2                                                                               Strange                                                                              
    

    Edit: And then Dave just ninja-solved the riddle.

You must be logged in to reply to this topic.