How to create a JSON object with array in Powershell - json

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

Related

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 output json format not correct

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.

Inputting JSON data in Powershell

Currently, I'm attempting to call upon an API to run a POST, with JSON data as the body. So I was wondering if anyone would be able to tell me how I need to format the text below inside the variable $postParams. I'm pretty new at working with JSON so I'm having so trouble with this.
Currently, I only have the following and don't know what to do about the second line on.
$postParams = #{name='Example'}
Here's is the entire data I was hoping to add to $postParams. So if you could help me with the 2nd, 4th, and 8th that'd be awesome. Thanks!
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
You'll need a here-string and ConvertFrom-Json.
here-string:
Quotation marks are also used to create a here-string. A here-string is a single-quoted or double-quoted string in which quotation marks are interpreted literally. A here-string can span multiple lines. All the lines in a here-string are interpreted as strings, even though they are not enclosed in quotation marks.
The resulting code:
# Use a PowerShell here string to take JSON as it is
$jsonString = #"
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
"#
# Pipe the string to create a new JSON object
$jsonObject = $jsonString | ConvertFrom-Json
# The resulting JSON object has properties matching the properties in the orig. JSON
$jsonObject.name
$jsonObject.url
# Nested property
$jsonObject.template.name
# Nested property in array
$jsonObject.groups[0].name
I've posted an online version of the above code at tio.run, so you can play around with it.
If you want to update several properties of the $jsonObject you can do the following:
$jsonObject.name = "NEW NAME"
$jsonObject.url = "NEW URL"
$jsonObject | ConvertTo-Json
ConvertTo-Json will take your object and create an appropriate JSON string:
{
"name": "NEW NAME",
"template": {
"name": "Template"
},
"url": "NEW URL",
"page": {
"name": "Landing Page"
},
"smtp": {
"name": "Sending Profile"
},
"launch_date": "2019-10-08T17:20:00+00:00",
"send_by_date": null,
"groups": [
{
"name": "test group"
}
]
}
If you $jsonObject has more than two levels of depth, use the -Depth parameter, otherwise not all object information will be included in the JSON string.
ConvertTo-Json:
-Depth
Specifies how many levels of contained objects are included in the JSON representation. The default value is 2.
Here is a tio.run link to a ConvertTo-Json example.
Hope that helps.
I can't test it currently, but try this.
$postParams = #'
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
'#
Make a hashtable, then convert to JSON:
$Hashtable = #{
Key1 = "Value1"
Key2 = "Value2"
}
$Json = $Hashtable | ConvertTo-Json

PowerShell json duplicate keys, condense values to single array

Is there a best practice for handling JSON documents with duplicated keys in PowerShell?
Ideally would like to compile the values of said keys into a single array mapped to the key.
For example:
{
"column01" : "id1",
"column02" : "id2",
"column03: : "id3",
"column03" : "id4"
}
Transformed to:
{
"column01" : "id1",
"column02" : "id2",
"column03: : [
"id3",
"id4"
]
}
I have been exploring options with the ConvertTo-Json cmdlet, but have not found a solution.
Appreciate the help!
While JSON does allow duplicate keys, this is not recommended and I suggest handling this by normalizing the JSON. Otherwise you can certainly pass your JSON with the duplicate key to ConvertFrom-Json but this won't result in your desired output.
It should be...
$obj = #"
{ "column01" : "id1",
"column02" : "id2",
"column03" : ["id3", "id4"]
}
"#
Then using $json = $obj | ConvertFrom-Json to convert into a powershell obj.
Then you can do the same with a PowerShell object and convert to JSON.
$obj = #{
"column01" = "id1";
"column02" = "id2";
"column03" = ("id3", "id4")
}
$json = $obj | ConvertTo-Json
$json
If you want to know how to normalize the data, I suggest you either edit your question or ask a new one.

ConvertFrom-Json : Cannot convert the JSON string because a dictionary that was converted from the string contains the duplicated keys

The following JSON is getting returned from OData API service:
{
"d": {
"results": [
{
"FileSystemObjectType": 0,
"Id": 1,
"ContentTypeId": "0x0100BC97B2F575CB0C42B79549F3BABD32A8",
"Title": "Nokia California",
"Address": "200 South Matilda Avenue\nW Washington Ave\n94086 Sunnyvale, California\nUnited States of America",
"ID": 1,
"Modified": "2014-02-24T10:06:39Z",
"Created": "2014-02-24T10:06:39Z",
"AuthorId": 12,
"EditorId": 12,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "d12aafad-502a-4968-a69e-36a7ea05ec80"
}
]
}
}
and saved as a string into variable named $data
An attempt to convert a JSON-formatted string to a custom object using ConvertFrom-Json cmdlet:
$results = $data | ConvertFrom-Json
gives the following error:
ConvertFrom-Json : Cannot convert the JSON string because a dictionary
that was converted from the string contains the duplicated keys 'Id'
and 'ID'.
Is there any way to convert the specified JSON-formatted string in PowerShell?
This is how I have done with it:
$results = $data.ToString().Replace("ID", "_ID") | ConvertFrom-Json
Note, both examples assume the JSON is stored in the $jsonstring variable.
In PowerShell Core, ConvertFrom-Json -AsHashtable is the easiest alternative:
$json = $jsonstring | ConvertFrom-Json -AsHashtable
$json['d']['results']
Name Value
---- -----
Modified 2/24/2014 10:06:39 AM
Title Nokia California
Attachments False
ID 1
ContentTypeId 0x0100BC97B2F575CB0C42B79549F3BABD32A8
GUID d12aafad-502a-4968-a69e-36a7ea05ec80
Created 2/24/2014 10:06:39 AM
EditorId 12
AuthorId 12
Address 200 South Matilda Avenue…
Id 1
OData__UIVersionString 1.0
FileSystemObjectType 0
In Windows PowerShell, you can use the Deserialize(String, Type) method from the JavaScriptSerializer Class.
Add-Type -AssemblyName System.Web.Extensions
$serializer = [Web.Script.Serialization.JavaScriptSerializer]::new()
$json = $serializer.Deserialize($jsonstring, [hashtable])
$json['d']['results']
In PowerShell V1.0, or in PowerShell V2.0 when the JSON is too big, I still use a convertion to XML :
Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization
function Convert-JsonToXml
{
PARAM([Parameter(ValueFromPipeline=$true)][string[]]$json)
BEGIN
{
$mStream = New-Object System.IO.MemoryStream
}
PROCESS
{
$json | Write-String -stream $mStream
}
END
{
$mStream.Position = 0
try
{
$jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($mStream,[System.Xml.XmlDictionaryReaderQuotas]::Max)
$xml = New-Object Xml.XmlDocument
$xml.Load($jsonReader)
$xml
}
finally
{
$jsonReader.Close()
$mStream.Dispose()
}
}
}
Using this code you can loop thru your items you can test :
$a = Get-Content C:\temp\jsontest.txt
$b.root.d.results.Item
$b.root.d.results.Item[7].Id[0].InnerText
(Edited)
In you case I would only replace the expected duplicate ID/Id
$data = Get-Content C:\temp\jsontest.txt -Raw
$datacorrected = $a -creplace '"Id":','"Id-minus":'
$psJsonIn = $datacorrected | ConvertFrom-Json
If really you've got unexpected duplicate you can write a function that trap the convertion error due to duplicated key and replace one.
ConvertFrom-JSON it going to try to create a PS Custom Object from the JSON string. PowerShell object property names are case-insensitive, so "ID" and "id" represent the same property name. You're going to have to do something with those duplicate property names in your JSON before you try to do that conversion, or it's going to fail.
I used the ToLower() before converting the json to object, resolved my issue.
$sdf = $data.ToLower() | ConvertFrom-Json