How to assign a name to JSON Array in Perl - json

In my script to_json() converting loop_data in json format and assigning to $json.
my $json = to_json(\#loop_data);
print $json;
gives this output.
[
{
"Name": "Vivek",
"Age": 20
},
{
"Name": "Sonali",
"Age": 19
}
]
But instead of that i want print $json to give this output.
{"Friends" : [
{
"Name": "Vivek",
"Age": 20
},
{
"Name": "Sonali",
"Age": 19
}
]}
Where to add "Friends" and {}.

You could pass a reference to a hash with Friends as the key and a reference to your array as the value:
my $json = to_json({"Friends" => \#loop_data});

Related

How do I add names to objects in JSON using PowerShell?

I have the following situation below. I'd like to add a name to each item in the array.
First item needs to have a name instead of being an anonymous object. How do I do this?
Items need to have an name derived from the Technical Name, so 988 instead of N988AB1.
Structure of array is changed to an object in the result.
Current situation:
{
"Category": [{
"TechnicalName": "N988AB1",
"Name": "House"
},
{
"TechnicalName": "H181AG3",
"Name": "Apartment"
},
{
"TechnicalName": "X123XY5",
"Name": "Villa"
}
]
}
Desired situation:
{
"Data": {
"988": {
"TechnicalName": "N988AB1",
"Name": "House"
},
"181": {
"TechnicalName": "H181AG3",
"Name": "Apartment"
},
"0123": {
"TechnicalName": "X0123XY5",
"Name": "Villa"
}
}
}
One way of tackling this: (You can copy and paste the full contents of the code box to try it out. I've commented what various steps are doing)
$ExistingJson = #"
{
"Category": [{
"TechnicalName": "N988AB1",
"Name": "House"
},
{
"TechnicalName": "H181AG3",
"Name": "Apartment"
},
{
"TechnicalName": "X123XY5",
"Name": "Villa"
}
]
}
"#
# Convert the json string to an object we can manipulate.
$ExistingObj = $ExistingJson | ConvertFrom-Json
# Create an empty hashtable for the new items we are creating.
$HT = #{}
foreach ($Category in $ExistingObj.Category) {
# Match any digits, grouped as "name", after any character [A-Za-z] which are followed by [A-Za-z] - this is pretty basic and may need to be changed if your TechnicalName string changes, or you want different information from it.
[System.Void]($Category.TechnicalName -match "(?<=[A-Za-z])(?<name>\d+)(?=[A-Za-z])")
$NewItem = [PSCustomObject]#{
TechnicalName = $Category.TechnicalName
Name = $Category.Name
}
# Add a new entry to the hashtable with the discovered digits by it's group name "name" and the object created above with the existing information as it's value.
$HT.Add($Matches["name"], $NewItem)
}
# Create a new object with a Data property with the value as the hashtable.
$NewObj = [PSCustomObject]#{
Data = $HT
}
# Convert it back to Json
$NewObj | ConvertTo-Json
Results in:
{
"Data": {
"988": {
"TechnicalName": "N988AB1",
"Name": "House"
},
"181": {
"TechnicalName": "H181AG3",
"Name": "Apartment"
},
"123": {
"TechnicalName": "X123XY5",
"Name": "Villa"
}
}
}

Combining all key value pairs in one using jq filter or jq play

I want to transform JSON data using jq filter
Json data:
{
"main": [
{
"firstKey": "ABCD",
"id": "12345",
"data": [
{
"name": "first_id",
"value": "first_id_value"
},
{
"name": "second_id",
"value": "second_id_value"
},
{
"name": "third_id",
"value": "third_id_value"
}
]
}
]
}
Expected OUTPUT:
{
"firstKey": "ABCD",
"id": "12345",
"data.name.first_id": "first_id_value",
"data.name.second_id": "second_id_value",
"data.name.third_id": "third_id_value"
}
After many trials and errors, I was near to expected output using following filter expression
[.main[]|{"firstKey", "id"},foreach .data[] as $item (0; "data.name.\($item.name)" as $a|$item.value as $b| {($a): $b})][]
Used foreach as objects under "data" are dynamic. the number of objects can differ.
The output for the above expression is:
{
"firstKey": "ABCD",
"id": "12345"
}
{
"data.name.first_id": "first_id_value"
}
{
"data.name.second_id": "second_id_value"
}
{
"data.name.third_id": "third_id_value"
}
But I want the objects of data to be under the same braces as 'firstKey' and 'id'.
LINK to JqPlay
Any suggestions will be helpful.
Since your structure is so rigid, you can cheat and use the built-in from_entries, which takes a list of {key, value} pairs and constructs an object:
.main[] |
{firstKey, id} +
(.data | map({key: "data.name.\(.name)", value}) |
from_entries)

Use Powershell variable in JSON

I am trying to pass a parameter through a function in powershell but it is not working
Code
function test($test1, $test2)
{
$details = #"
{ "updateDetails": [
{
"customer": "John",
"rank": $test1
},
{
"school": "western",
"address": $test2
}
]
}
"#
return $details
}
test 0 florida
Current issue
{ "updateDetails": [
{
"customer": "John",
"rank":
},
{
"school": "western",
"address": florida
}
]
}
I tried running test but the value 0 is not filled in the details json, florida is filled in correctly. How can I replace the two values. Also how can florida be in string
0 fills in for me, but florida doesn't have quotes, which is invalid JSON.
To make life a little easier, instead building a here-string, consider building an object and converting it to JSON with the built-in cmdlet ConvertTo-Json.
In this example I'll show you how to do it using a hashtable
function test($test1, $test2)
{
$details = #{
"updateDetails"=
#(
#{
"customer" = "John"
"rank" = $test1
},
#{
"school" = "western"
"address" = $test2
}
)
}
return $details | ConvertTo-Json
}
test 0 florida
output
{
"updateDetails": [
{
"customer": "John",
"rank": 0
},
{
"school": "western",
"address": "florida"
}
]
}
Your code is perfectly fine. I ran your example and it worked as expected. Maybe you missed updating the function. Close the shell and then try again.
To include "florida" as string you could simply add quotes around the variable "$test2", or even safer: Use ConvertTo-Json to output a properly quoted and escaped JSON string:
function test {
param ([int]$rank, [string]$address)
return #"
{ "updateDetails": [
{
"customer": "John",
"rank": $rank
},
{
"school": "western",
"address": $(ConvertTo-Json $address)
}
]
}
"#
}
test 0 florida

How to add keys to values and convert to json in PowerShell?

I have a string like this:
$string = "PackageName1,1,C:\Path
PackageName2,12,C:\Path2
PackageName3,3,C:\Path3"
(is a file with multilines, when I get the content I have the string above)
I want to convert this string to Json:
[
{
Pacakge: "PackageName1",
Branch: = "1",
LocalPath = "C:\Path"
}
{
Pacakge: "PackageName2",
Branch: = "2",
LocalPath = "C:\Path2"
}
]
I can get the values with this code:
$spiltted = $string.Split(' ')
ForEach ($s in $splitted)
{
$values = $s.Split(',')
}
How can I add the Json keys to each value and convert it to Json object?
Thank you.
As your String looks like a csv without headers:
$string | ConvertFrom-Csv -Header Package,Branch,LocalPath|ConvertTo-Json
Sample output
[
{
"Package": "PackageName1",
"Branch": "1",
"LocalPath": "C:\\Path"
},
{
"Package": "PackageName2",
"Branch": "12",
"LocalPath": "C:\\Path2"
},
{
"Package": "PackageName3",
"Branch": "3",
"LocalPath": "C:\\Path3"
}
]

How to format a csv file using json data?

I have a json file that I need to convert to a csv file, but I am a little wary of trusting a json-to-csv converter site as the outputted data seems to be incorrect... so I was hoping to get some help here!
I have the following json file structure:
{
"GroupName": "GrpName13",
"Number": 3,
"Notes": "Test Group ",
"Units": [
{
"UnitNumber": "TestUnit13",
"DataSource": "Factory",
"ContractNumber": "TestContract13",
"CarNumber": "2",
"ControllerTypeMessageId" : 4,
"NumberOfLandings": 4,
"CreatedBy": "user1",
"CommissionModeMessageId": 2,
"Details": [
{
"DetailName": "TestFloor13",
"DetailNumber": "5"
}
],
"UnitDevices": [
{
"DeviceTypeMessageId": 1,
"CreatedBy": "user1"
}
]
}
]
}
The issue I think Im seeing is that the converters seem to not be able to comprehend the many nested data values. And the reason I think the converters are wrong is because when I try to convert back to json using them, I dont receive the same structure.
Does anyone know how to manually format this json into csv format, or know of a reliable converter than can handle nested values?
Try
www.json-buddy.com/convert-json-csv-xml.htm
if not working for you then you can try this tool
http://download.cnet.com/JSON-to-CSV/3000-2383_4-76680683.html
should be helpful!
I have tried your json on this for url:
http://www.convertcsv.com/json-to-csv.htm
As a result:
UnitNumber,DataSource,ContractNumber,CarNumber,ControllerTypeMessageId,NumberOfLandings,CreatedBy,CommissionModeMessageId,Details/0/DetailName,Details/0/DetailNumber,UnitDevices/0/DeviceTypeMessageId,UnitDevices/0/CreatedBy
TestUnit13,Factory,TestContract13,2,4,4,user1,2,TestFloor13,5,1,user1
Because it could save the path of the key,like the 'DeviceTypeMessageId' in list 'UnitDevices': it will named the columns name with 'UnitDevices/0/DeviceTypeMessageId', this could avoid the same name mistake, so you can get the columns name by its converter rules.
Hope helpful.
Here is a solution using jq
If the file filter.jq contains
def denormalize:
def headers($p):
keys_unsorted[] as $k
| if .[$k]|type == "array" then (.[$k]|first|headers("\($p)\($k)_"))
else "\($p)\($k)"
end
;
def setup:
[
keys_unsorted[] as $k
| if .[$k]|type == "array" then [ .[$k][]| setup ]
else .[$k]
end
]
;
def iter:
if length == 0 then []
elif .[0]|type != "array" then
[.[0]] + (.[1:] | iter)
else
(.[0][] | iter) as $x
| (.[1:] | iter) as $y
| [$x[]] + $y
end
;
[ headers("") ], (setup | iter)
;
denormalize | #csv
and data.json contains (note extra samples added)
{
"GroupName": "GrpName13",
"Notes": "Test Group ",
"Number": 3,
"Units": [
{
"CarNumber": "2",
"CommissionModeMessageId": 2,
"ContractNumber": "TestContract13",
"ControllerTypeMessageId": 4,
"CreatedBy": "user1",
"DataSource": "Factory",
"Details": [
{
"DetailName": "TestFloor13",
"DetailNumber": "5"
}
],
"NumberOfLandings": 4,
"UnitDevices": [
{
"CreatedBy": "user1",
"DeviceTypeMessageId": 1
},
{
"CreatedBy": "user10",
"DeviceTypeMessageId": 10
}
],
"UnitNumber": "TestUnit13"
},
{
"CarNumber": "99",
"CommissionModeMessageId": 99,
"ContractNumber": "Contract99",
"ControllerTypeMessageId": 99,
"CreatedBy": "user99",
"DataSource": "Another Factory",
"Details": [
{
"DetailName": "TestFloor99",
"DetailNumber": "99"
}
],
"NumberOfLandings": 99,
"UnitDevices": [
{
"CreatedBy": "user99",
"DeviceTypeMessageId": 99
}
],
"UnitNumber": "Unit99"
}
]
}
then the command
jq -M -r -f filter.jq data.json
will produce
"GroupName","Notes","Number","Units_CarNumber","Units_CommissionModeMessageId","Units_ContractNumber","Units_ControllerTypeMessageId","Units_CreatedBy","Units_DataSource","Units_Details_DetailName","Units_Details_DetailNumber","Units_NumberOfLandings","Units_UnitDevices_CreatedBy","Units_UnitDevices_DeviceTypeMessageId","Units_UnitNumber"
"GrpName13","Test Group ",3,"2",2,"TestContract13",4,"user1","Factory","TestFloor13","5",4,"user1",1,"TestUnit13"
"GrpName13","Test Group ",3,"2",2,"TestContract13",4,"user1","Factory","TestFloor13","5",4,"user10",10,"TestUnit13"
"GrpName13","Test Group ",3,"99",99,"Contract99",99,"user99","Another Factory","TestFloor99","99",99,"user99",99,"Unit99"