ConverTo-Json altering intended output - powershell

I have a psobject that is created from the JSON output of an Invoke-RestMethod. My intention is to change one value, convert back to JSON, then add back to the application REST API with another Invoke-RestMethod. I have done this several times in the past with the same REST API so I'm not sure why this one isn't working.
The psobject $restOut looks like this:
id: 123
limit: #{limitMb=0; limitPercent=0}
The next block of code changes the id if the new id I want isn't already set
$newId = 456
if($restOut.id -ne $newId){
$restOut.id = $newId
$inputJson = $restOut | ConvertTo-Json -Depth 2
Invoke-RestMethod -Uri $restURl -Method PUT -Body $inputJson
}
I'm expecting $inputJson to look like this (and the psobject $restOut does match the expectation):
{
"id": "456",
"limit": {
"limitMb": 0,
"limitPercent": 0
}
}
But what I'm actually getting is:
{
"id": {
"value": "456",
"id": "456"
},
"limit": {
"limitMb": 0,
"limitPercent": 0
}
}
As said, I've done this exact manipulation many times in other scripts targeting the same software API, and am just at a loss with the behavior this time. Any help is appreciated. Thanks!

Easy fix
This was a simplified sample. In my actual script $newId = 456 was actually being assigned from another API call. Therefore it was also an object. Simply quoting it in the line that changes the id to make it a string fixed the issue:
$restOut.id = "$newId"
instead of
$restOut.id = $newId

Related

Issue with API result not converting to object in powershell

I have an odd problem. I'm getting some data back from an API and storing it in $response
The result looks like this (I've changed the names and IDs):
accountId : 1234
secureScoreProgress : #{startDate=2022-12-12 00:00:00.000; endDate=2023-01-26 00:00:00.000; totalDays=2738; minScore=76; maxScore=534.18; averageScore=257.33; data=System.Object[]}
monitoredAccounts : #{total=479; data=System.Object[]}
accountIdToNameMap : #{1234=Apple; 5432=Microsoft; 2584=Tesla; 7533=Ben and Jerry; 7534=Micool Paul Inc; 7549=AGLX; 7558=Samsung}
I'm interested in the 'accountIdToNameMap' section, so I store it to an object like so:
$accounts = $response.accountIdToNameMap
This returns the following list:
1234 : Apple
5432 : Microsoft
2584 : Tesla
7533 : Ben and Jerry
7534 : Micool Paul Inc
7549 : AGLX
7558 : Samsung
If I try to do a foreach on the list, it only loops once and outputs that whole list in one go.
I've tried to ConvertFrom-JSON but that throws Invalid JSON primitive: .
I've tried to ConvertTo-JSON, which works, but I still can't loop through the results. After ConvertTo-JSON, the result looks like this:
{
"1234": "Apple",
"5432": "Microsoft",
"2584": "CH Hausmann",
"7533": "Hughes Fowler Carruthers",
"7534": "Tempest Resourcing",
"7549": "Cream UK Ltd",
"7558": "Illuminatis / Scout Data"
}
What am I doing wrong?
If I try to do a foreach on the list
It's not a list, it's an object. You can enumerate its properties by accessing the hidden psobject member:
foreach ($property in $accounts.psobject.Properties) {
"The `$accounts object has a property named '$($property.Name)' with value '$($property.Value)'"
}
You can use this to build a hashtable (an unordered dictionary):
$idToNameMap = #{}
foreach ($property in $accounts.psobject.Properties) {
$idToNameMap[$property.Name] = $property.Value
}
Now you can easily use it as a lookup table:
$idToNameMap['1234'] # resolves to "Apple"

Powershell Append PSCustomObject to nested PSCustomObject

My problem is that I have a remote API giving me a JSON with 10 levels deep nesting and I need to add another array/hashtable/PSCustomObject (whatever you want to call it) to one of them.
The JSON looks like this:
{
"result": [
"modules": [
"data": {
"segments": [
{
"routes": {
"static": [
{
"destination": "10.0.0.0",
"netmask": "255.0.0.0"
},
{
"destination": "172.16.0.0",
"netmask": "255.240.0.0"
}
]
}
}
]
}
]
]
}
The return object is a Hashtable, however when I try to access the values in dot notation, it turns into PSCustomObject:
$statics = $result.result.modules.data.segments.routes.static
It won't let me use the other notation:
$statics = $result['result']['modules']['data']['segments']['routes']['static']
Error: Cannot index into a null array
The real tricky part (for me) is to to append a new hastable to the "static" hashtable in such a way that the rest of the hashtable remains intact.
$newroute = #{
destination = "1.1.1.1."
netmask = "255.255.255.255"
}
I would have used PHP or Python but for this project I must use Powershell and I'm running into all sorts of things where PS behaves different from what I expect.
Any help is greatly appreciated!
static is an array, you can add new items to it:
$newStaticRoute = [pscustomobject]#{
destination = '192.168.0.0'
netmask = '255.255.0.0'
}
$result.result.modules.data.segments.routes.static += $newStaticRoute

How to filter a part of an output in powershell

I'm struggling with filtering the sessionId from the following output:
status messages data
------ -------- ----
Success {#{code=success; message=Success}} #{sessionId=0662c4d429bb51ef772e875f9c9b3a46; faSessionId=qfvio0382283ihbknhfh70kvn4; phpSessionId=qfvio0382283ihbknhfh70kvn4}
I've tried with the following:
$sessionId = $response | select "data"
This is returning:
data
----
#{sessionId=f77d5bfb5bdc65163e605d9c7edbcaed; faSessionId=hrsbd5iuq8i6dttfhimpm5baf1; phpSessionId=hrsbd5iuq8i6dttfhimpm5baf1}
I can't get it working to only extract the sessionId part.
It would be great if anyone could assist with the correct PowerShell code to obtain this.
It might help to think of the object you're working with like this, in JSON.
{
"Status": "Success",
"Messages": {
"code": "success",
"message": "Success"
},
"Data": {
"faSessionId": "qfvio0382283ihbknhfh70kvn4",
"phpSessionId": "qfvio0382283ihbknhfh70kvn4",
"sessionId": "0662c4d429bb51ef772e875f9c9b3a46"
}
}
You want the sessionId propeerty so you're selecting Data, but then you're finding that Data actually has those other properties of phpSessionId and faSessionId. Fortunately you have two approaches to get what you need.
Continue using the Select-Object cmdlet
You are already using this cmdlet but using the alias of Select, so you can keep using Select-Object to drill down all the way to the center of the Earth basically.
$response | Select-Object -ExpandProperty Data | Select-Object -ExpandProperty sessionId
>0662c4d429bb51ef772e875f9c9b3a46
Drill into the property you want with Dereferencing
This is the more programmery way to do it but is very popular. It's also called dot-notation.
$response.Data.sessionId
0662c4d429bb51ef772e875f9c9b3a46

Retrieve value from Json object with field having dots and hyphen in powershell

I want to retrieve value of a field present in json object. The filed name has dots and hyphen.
For eg:
$json = #"
{
"Stuffs":
{
"Name.new-name": "Darts",
"Type": "Fun Stuff"
}
}
"#
How can I get the value Darts?
I tried some approaches like
$x = $json | ConvertFrom-Json
$x.Stuffs.(Name.new-name)
But it doesn't work.
Try this
$x.Stuffs.'Name.new-name'

Power BI REST API query parameters

I am using the new query parameters API https://msdn.microsoft.com/en-us/library/mt845781.aspx
I am able to call parameters fine, however when trying to set them I get an error message. After parsing the error I get this
VERBOSE: POST https://api.powerbi.com/v1.0/myorg/groups/e7229a42-46ef-4d80-b8ca-e42909509dbb/datasets/5ef116d7-917... with -1-byte payload
error : #{code=InvalidRequest; message=Dataset Parameters list is invalid in 5ef116d7-9179-40a2-8a30-a657265dfe4a. Reason: Empty;
target=5ef116d7-9179-40a2-8a30-a657265dfe4a}
I don't understand because the parameters list is not empty? I have created a physical table with the parameters and tried and then also created a list of values in the manage parameters settings and it still gives the same error.
PowerShell -
$parametername = "YourData"
$parametervalue = "Company1"
#POST body
$postParams = #{
"name" = "$parametername"
"newValue" = "$parametervalue"
}
JSON from documentation (I am not including updatedetails in PowerShell because I don't know how)
"updateDetails": [
{
"name": "MaxId",
"newValue": "5678"
},
{
"name": "StrParam",
"newValue": "Another Hello"
}
]
}
You can find the solution here
You just need to enable the Load for the parameters