Powershell ConvertFrom-Json output json format not correct - json

I have a json file, i converted that by using ConvertFrom-json but the output i am getting below.
Get-Content ".\example1.JSON" | ConvertFrom-Json
Output i am getting as below
---------------------------------
Result
------
{#{_id=5f0bdeec01c99848bcbbba07; index=0; guid=a1c59de9-94c9-4a53-9a18-61a35457b7a2; isActive=False; balance=$3,782.46; picture=http://placehold.it/32x32; age=28; eyeColor=blue; ...
But i want this should be in below format because of "{"Result":" it is not coming in proper format can someone suggest how to overcome ?
_id : 5f0bdeec01c99848bcbbba07
index : 0
guid : a1c59de9-94c9-4a53-9a18-61a35457b7a2
isActive : False
balance : $3,782.46
picture : http://placehold.it/32x32
age : 28
eyeColor : blue
name : Tran Rodriquez
gender : male
company : VIRVA
email : tranrodriquez#virva.com
phone : +1 (908) 426-2103
address : 222 Crosby Avenue, Frierson, Louisiana, 613
Here's sample content of the JSON file:
{
"Result": [
{
"id": 10,
"name": "shirt",
"color": "red",
"_id": "5f0bdeec01c99848bcbbba07",
"host": "tester1"
},
{
"id": 11,
"name": "coat",
"color": "black",
"price": "$2300"
}
]
}

You need to access the .Result property in order to have the (nested) object it contains format properly:
(Get-Content -Raw .\example1.JSON | ConvertFrom-Json).Result
Note the use of -Raw, which makes Get-Content read the file as a whole, as a single string - while not strictly necessary, this speeds up processing, given that ConvertFrom-Json needs to collect all input first anyway.
An object that is nested inside another object as a property value is formatted using a single-line, hash-table literal-like representation, as you've experienced.
A simple example:
PS> [pscustomobject] #{ foo = 1; bar = [pscustomobject] #{ baz = 2 } }
foo bar
--- ---
1 #{baz=2}
Note the representation of the nested custom object stored in the .bar property.
This hash-table literal-like representation is the stringification of [pscustomobject] instances, as (also) used in expandable strings; e.g., "$([pscustomobject] #{ baz = 2 })" yields '#{baz=2}' - see this answer for details.

Related

Updating JSON Array of Objects with NULL Value in Powershell When Key is Present

I am new to Powershell and am having trouble doing something that I imagine may be pretty simple, but not having luck so far.
I have an array with two objects in it. It looks like this basically:
[
{
"name":"John",
"age":30,
...
...
},
{
"score":null,
"vehicle":"Camaro",
"engine":"V8",
...
...
}
]
My goal is to update the score value in the second object. I have had luck doing so when the key's value is already present as a String, but am not understanding why I am unable to get this to work when the key is present but the value is null (as shown above).
I have tried using a function which I learned about when doing a search for a previously posted question trying to do something similar:
Set Value of Nested Object Property by Name in PowerShell
The function from that question looks like this:
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { $object.$p1 = $Value }
}
and can be called like this:
SetValue -object $Obj -key $Key -Value $Value
I am not sure why it matters if the value is NULL or not. It can find the key, but just not doing anything if its value is NULL.
My apologies if this already out there. Powershell is just a little different than anything I have worked with before! Any help is greatly appreciated! :)
The object generated by your JSON string is an array of two objects:
$json = #'
[
{
"name":"John",
"age":30,
},
{
"score":null,
"vehicle":"Camaro",
"engine":"V8"
},
]
'# | ConvertFrom-Json
$json[0] # => Element 0 of the Array
name age
---- ---
John 30
$json[1] # => Element 1 of the Array
score vehicle engine
----- ------- ------
Camaro V8
Updating the Value of the score property considering the JSON will always be the same, meaning, the element 1 of the array will always have that property would be as simple as:
$json[1].score = 'hello' # => Updating the property value
$json | ConvertTo-Json # => Converting the array back to Json
[
{
"name": "John",
"age": 30
},
{
"score": "hello",
"vehicle": "Camaro",
"engine": "V8"
}
]
On the other hand, if the arrangement of the objects wouldn't be always the same, you could loop over all elements of the array searching for that property and, once found, update it. For example:
# For each element of the array
foreach($object in $json) {
# if this object has a property with name `score`
# assign that `NoteProperty` to the variable `$prop`
if($prop = $object.PSObject.Properties.Item('score')) {
# update the Value of the `NoteProperty`
$prop.Value = 'hello'
}
}
$json | ConvertTo-Json # Convert it back

Populate collection of objects from one JSON file to the collection of another one with PowerShell

I have two JSON files and want to transfer collection of objects from one file to another. Suppose, the from.json file contains property which represents collection of clients:
"Clients":
[
{
"Name": "Name1",
"Age": "12"
},
{
"Name": "Name2",
"Age": "14"
}
]
to.json file contains an empty collection, "Objects: []" ,which must be filled with objects from from.json. Each objects in toJson variable must contain additional property - Id, so eventually, my "to.json" file should look like this:
"Objects":
[
{
"Id": "{new-id}",
"Name": "Name1",
"Age": "12"
},
{
"Id": "{new-id}",
"Name": "Name1",
"Age": "12"
}
]
I've converted two files into variables:
$fromJson = (Get-Content -Raw -Path {fromPath}) | ConvertFrom-Json
$toJson = (Get-Content -Raw -Path {toPath}) | ConvertFrom-Json
I know that objects from fromJson to toJson can be transferred in the following manner:
toJson.Objects += fromJson.Clients, but that's not enough in my case. I think that it could be done by iterating through fromJson.Clients array but have no idea how to create an object and add it into toJson.Objects collection.
Here's a more efficient solution, based on:
Use of a calculated property with Select-Object, which allows you to place the new property first in the output objects.
Instead of building the array one by one with += (which is inefficient, because a new array must technically be created behind the scenes in every iteration), the solution below lets PowerShell collect the output objects of the Select-Object call in an array automatically (the [array] type constraint is needed to ensure that an array is created even if only one object happens to be output.)
# Sample input.
$fromJson = ConvertFrom-Json '{"Clients":[{"Name":"Name1","Age":"12"},{"Name":"Name2","Age":"14"}]}'
$toJson = ConvertFrom-Json '{ "Objects": [] }'
[array] $toJson.Objects =
$fromJson.Clients |
Select-Object #{ Name='Id'; Expression = { [string] (New-Guid) } }, *
$toJson | ConvertTo-Json -Depth 3 # append | Set-Content as needed.
Kind of new to the PowerShell, but after a bit of investigation came up with the following solution:
fromJson.Clients | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name 'Id' -Value ([guid]::NewGuid().Guid.ToString())
$toJson += $_
}
...
$toJson | ConvertTo-Json | Out-File {to.json_path}
Frankly, don't know if that is a 'proper' way to do that, but generally it works for that particular case. For now, see no other solution.

PowerShell - ConvertFrom-Json fails to properly serialize JSON array of items with mixed properties [duplicate]

This question already has an answer here:
Script has two variables when done, but when I pipe to SELECT-object only first one returns data to console
(1 answer)
Closed 1 year ago.
I'm working on a PowerShell client to a NoSQL-backed database. Not all of the documents in the table I query have the exact same set of properties. When using ConvertFrom-Json to serialize this payload the first JSON array item dictates the properties available to all other objects in the JSON payload.
Example:
#"
[
{
"thing1": "bob",
"thing2": "mary"
},
{
"thing1": "bob",
"thing2": "mary",
"thing3": "tom"
}
]
"# | ConvertFrom-Json
thing1 thing2
------ ------
bob mary
bob mary
#"
[
{
"thing1": "bob",
"thing2": "mary",
"thing3": "tom"
},
{
"thing1": "bob",
"thing2": "mary"
}
]
"# | ConvertFrom-Json
thing1 thing2 thing3
------ ------ ------
bob mary tom
bob mary
Is this expected behavior? Is there a way around this other than attempting to parse the raw JSON on my own?
I'm currently using PowerShell 5.1:
$PSVersionTable
Name Value
---- -----
PSVersion 5.1.18362.1801
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.18362.1801
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
This is not an issue with ConvertFrom-Json. This is related to Write-Output missing columns. The reason is that PowerShell formats output as a table by default and uses the first row to format all rows. Just observe how these two objects are displayed.
[PSCustomObject]#{
a=1;
}
[PSCustomObject]#{
a=2;b=3;
}
Try formatting output as list not a table to see that ConvertFrom-Json does not lose columns.
$json | ConvertFrom-Json|Format-List

How to create a JSON object with array in Powershell

I am a newbie to Powershell and I couldn't find this on googling but how do I build a json structure with an array inside? Is it through a custom object? Have been a bit confused by the syntax that I have seen online and not sure what is the recommended way to do it. Eventually I need to be able to save it to a JSON file too.
json_ret = {
"a": 4,
"b": [ {"c" : 5, "d": "text", "e": "foo"}]
}
Yes you can build a json object through a PSCustomObject:
[PSCustomObject]#{
a = 4
b = #([ordered]#{
c = 5
d = "text"
e = "foo"
})
} | ConvertTo-Json
First we create PSObject using its type accelerator PSCustomObject.
Then we define the root key and value "a", and we have to create an array inside "b".
The #() statement creates an array, but we can't we create key-value pairs in array. So we use #{} to create hashtable. Before it [ordered] flag says the hashtable to keep the exact structure as we have created it.
Then we define the array values, and after that close the internal array-hashtable.
Now we end the PSCustomObject and pipe it ConvertTo-Json. Now you get a converted json.
Footnotes
If you want to dump the json to a file, then use this:
[PSCustomObject]#{
a = 4
b = #([ordered]#{
c = 5
d = "text"
e = "foo"
})
} | ConvertTo-Json | Out-File "Filepath"
If you want to save json to a variable:
$variable = ([PSCustomObject]#{
a = 4
b = #([ordered]#{
c = 5
d = "text"
e = "foo"
})
} | ConvertTo-Json)
If you want to create the JSON document directly, as a string, it's simplest to use a verbatim here-string:
$json_ret = #'
{
"a": 4,
"b": [ {"c" : 5, "d": "text", "e": "foo"}]
}
'#
You can easily save that to a file with $json_ret | Set-Content file.json, for instance.
By contrast, if you want to construct your data as an object graph first, to be converted to JSON with ConvertTo-Json later, see Wasif_Hasan's helpful answer.
As for what you tried:
An unquoted { ... } construct is a script block, which is a piece of PowerShell code for later invocation on demand - and the contents of your JSON document happen not to constitute valid PowerShell code, causing construction of the script block to fail.
If using variables, then can create body including array like shown below, where $text is the variable. No need to user ConvertTo-Json and can easily copy the body from postman directly.
$text = "ABC"
# Post Body
$body = #"
{
"name" = "$text",
"description" = "$text",
"myArray": [
{
"id": "2c91808680d3c34b0180dc81d78c21e9",
"type": "myType",
"name": "myName"
}
]
}
"#
$body

Powershell - Retain Complex objects with ConvertTo-Json

Powershell command-let ConvertTo-Json has the following limitations
1) It returns Enum values as Integers instead of their text
2) It doesn't return the date in a readable format
For point #1 see below, Status and VerificationMethod Properties
PS C:\Windows\system32> Get-Msoldomain | ConvertTo-Json
{
"ExtensionData": {
},
"Authentication": 0,
"Capabilities": 5,
"IsDefault": true,
"IsInitial": true,
"Name": "myemail.onmicrosoft.com",
"RootDomain": null,
"Status": 1,
"VerificationMethod": 1
}
To handle this, I changed my command as below
PS C:\Windows\system32> Get-Msoldomain | ConvertTo-Csv | ConvertFrom-Csv | ConvertTo-Json
{
"ExtensionData": "System.Runtime.Serialization.ExtensionDataObject",
"Authentication": "Managed",
"Capabilities": "Email, OfficeCommunicationsOnline",
"IsDefault": "True",
"IsInitial": "True",
"Name": "curtisjmspartnerhotmail.onmicrosoft.com",
"RootDomain": "",
"Status": "Verified",
"VerificationMethod": "DnsRecord"
}
Now you see, that the enums are being returned with their text values above (Status and VerificationMethod) instead of their integer values.
However, There are a few limitations with this approach:
1) ConvertTo-Csv doesn't retain the Arrays or Complex Objects, and
outputs them as their Class Names (Watch the ExtensionData Properties
in both the outputs). In the second output, we tend to lose the data,
and just get the className
System.Runtime.Serialization.ExtensionDataObject as a string
2) Both ConvertTo-Csv and ConvertFrom-Csv are not the script-level
commandlets, but they are command-level commandlets, which means that
we can't use them at the end of the script , but they will have to be
used with the individual commands like I am doing above. WHEREAS,
ConvertTo-Json need not be applied at the commmandLevel, but just
applied once for the script output.
My question is:
1) How do I still use the convertTo-Json, so that all my enum properties are returned with their texts and not integers, and ALSO the Complex Objects or Arrays are not lost? In the approach I have used, the complex objects are getting lost
2) Also, it should be generic enough so that It can be applied at the end of the script, and not at the command level
ConvertTo-Json and ConvertTo-Csv are both forms of serializing objects in some sort of text representation and both are useful in different use cases.
ConvertTo-Csv is perhaps best used for 2-dimensional data that can be expressed in a table such as a spreadsheet. Hence it is awkward to try to convert "complex" objects, i.e. those with properties that contain other structured data, into a simple table. In such cases PowerShell represents such data as the full name of the data type.
ConvertTo-Json is capable of serializing more complicated objects, since the format allows for nested arrays/data structures, e.g. the ExtensionData property in your example. Note that you may need to use the -Depth parameter to ensure that deeply nested data is serialized correctly.
So the problem really comes down to how the ConvertTo-Json cmdlet serializes enums, which can be demonstrated with:
[PS]> (Get-Date).DayOfWeek
Tuesday
[PS]> (Get-Date).DayOfWeek.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DayOfWeek System.Enum
[PS]> Get-Date | Select DayOfWeek | ConvertTo-Json
{
"DayOfWeek": 2
}
So before you convert to JSON you need to ensure that the DayOfWeek property (in this example) or Status and VerificationMethod properties (from your example) are converted to their string equivalents first.
You can do this using an expression with Select-Object to convert the data as it passes down the pipe. Note that you do need to include all the properties that you want included in the final JSON:
[PS]> Get-Date |
Select DateTime,#{Label="DayOfWeek";Expression={$_.DayOfWeek.ToString()}} |
ConvertTo-Json
{
"DateTime": "13 June 2017 10:33:51",
"DayOfWeek": "Tuesday"
}
So in your case you'd need something like this:
[PS]> Get-Msoldomain |
Select-Object ExtensionData,IsDefault,IsInitial,Name,RootDomain `
,{Label="Authentication";Expression={$_.Authentication.ToString()}} `
,{Label="Capabilities";Expression={$_.Capabilities.ToString()}} `
,{Label="Status";Expression={$_.Status.ToString()}} `
,{Label="VerificationMethod";Expression={$_.VerificationMethod.ToString()}} |
ConvertTo-Json
#puneet, following your comment on my other answer, here is an example of how you might build up a new object, based on an existing one, with the Enum types converted to strings.
The idea is to create a new "empty" object, then loop through all the properties of the original object and add them to the new one, but if any of the original properties are Enums, then those are converted to strings.
$data = [PSCustomObject]#{}
(Get-Date).PSObject.Properties | Select Name,Value | Foreach-Object {
if($_.Value.GetType().BaseType.FullName -eq "System.Enum"){
$data | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value.ToString()
}
else {
$data | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value
}
}
$data | ConvertTo-Json
You may want to finesse this a little for your own application, but hopefully the idea behind it is clear. Definitely check to see that all the properties are being treated correctly in the JSON output.
to keep enum,array and date when converting psObject to json, you can use newtonsoft. a sample here https://github.com/chavers/powershell-newtonsoft using Nerdy Mishka powershell module.
$obj = New-Object pscustomobject -Property #{Enum = (Get-DAte).DayOfWeek; int = 2; string = "du text"; array = #("un", "deux", "trois"); obj= #{enum = (Get-DAte).DayOfWeek; int = 2; string = "du text"; array = #("un", "deux", "trois")}}
Import-Module Fmg-PrettyJson
$settings = Get-NewtonsoftJsonSettings
$enumconv = "Newtonsoft.Json.Converters.StringEnumConverter"
$e = New-Object $enumconv
$settings.Converters.Add($e)
Set-NewtonsoftJsonSettings $settings
$obj | ConvertTo-NewtonsoftJson
return:
{
"array": [
"un",
"deux",
"trois"
],
"enum": "Thursday",
"int": 2,
"obj": {
"enum": "Thursday",
"array": [
"un",
"deux",
"trois"
],
"int": 2,
"string": "du text"
},
"string": "du text"
}