I am very new to Windows PowerShell. I am trying to fire ConvertFrom-Json command for the below Json :-
$ret=[{"ID":"ABC","type":"Test","code":"AD","enabled":true,"sourceMappings":[{"source":"Test","values":[{"code":"AD","value":"Anderson","enabled":true,"canonicalValue":true,"downStreamDefaultValue":true}]}],"startDate":0,"endDate":0,"updatedBy":"YY","updateDate":1590085877449,"version":4}]
and I am getting below output :-
ID : ABC
type : Test
code : AD
enabled : True
sourceMappings : {#{source=Test; values=System.Object[]}}
startDate : 0
endDate : 0
updatedBy : YY
updateDate : 1590085877449
version : 4
If you notice the values been assigned to System.Object[].Please help me how to get the original values in the output.
I think the converting is all fine.
You can access the values via:
$tmp = $ret | ConvertFrom-Json
$tmp.sourcemappings
$tmp.sourcemappings.values.code
and so on
Lets first make your json file more readable:
{
"ID":"ABC",
"type":"Test",
"code":"AD",
"enabled":true,
"sourceMappings":[{"source":"Test","values":[{"code":"AD","value":"Anderson","enabled":true,"canonicalValue":true,"downStreamDefaultValue":true}]}],
"startDate":0,
"endDate":0,
"updatedBy":"YY",
"updateDate":1590085877449,
"version":4
}
Second of all, your way of defining json variable is incorrect. In powershell, you need to define json variables is surrounding the json content with #" and "#. The correct way to set $ret equal to your json file would be like this:
$ret=#"
{
"ID":"ABC",
"type":"Test",
"code":"AD",
"enabled":true,
"sourceMappings":[{"source":"Test","values":[{"code":"AD","value":"Anderson","enabled":true,"canonicalValue":true,"downStreamDefaultValue":true}]}],
"startDate":0,
"endDate":0,
"updatedBy":"YY",
"updateDate":1590085877449,
"version":4
}
"#
Where $ret would be considered a string data type. You could then convert the json with:
$var = ConvertFrom-Json -InputObject $ret
Where you could now interact with it like normal. For example, $var.ID would output ABC and if you tried checking the object type again with $var.gettype() it would output:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
Where the type would be a PSCustomObject
Update: It seems as if I misunderstood the question, my bad!
The reason it says
sourceMappings : {#{source=Test; values=System.Object[]}}
Is because powershell doesn't want to display the whole value since there are many components in the value. You can view the values in the sourceMappings class with $var.sourceMappings where the output would be:
source values
------ ------
Test {#{code=AD; value=Anderson; enabled=True; canonicalValue=True; downStreamDefaultValue=True}}
and you can keep on viewing deeper if you add on like $var.sourceMappings.code etc. etc.
Related
I am fairly new to PowerShell and am trying to use a module called PoshWAPI. This module is used to query Infoblox. One of the commands is Get-IBobject which allows me to query infoblox for a record type.
This is my code so far:
Set-IBConfig -ProfileName 'MyGrid' -WAPIHost dns.example.com -WAPIVersion latest -Credential (Get-Credential) -SkipCertificateCheck
$result = Get-IBObject -ObjectType record:host 'name=host1.network.example.com' -ReturnAll
That works well and returns the following
_ref : record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnRtY3MuaW5mb3NlYy5zMGE0OTFlMDAtMjMudDkwNC5zb25lc3N1czAx:host1.network.example.com/default
allow_telnet : False
comment : TOSD-37248
configure_for_dns : True
ddns_protected : False
disable : False
disable_discovery : False
dns_name : host1.network.example.com
extattrs :
ipv4addrs :{#{_ref=record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudG1jcy5pbmZvc2VjLnMwYTQ5MWUwMC0yMy50OTA0LnNvbmVzc3VzMDEuMTAuNzMuMzAuMTYu:10.73.30.16/host1.network.example.com/default;
configure_for_dhcp=False; host=host1.network.example.com; ipv4addr=10.73.30.16}}
name : host1.network.example.com
network_view : default
rrset_order : cyclic
use_cli_credentials : False
use_snmp3_credential : False
use_snmp_credential : False
use_ttl : False
view : default
zone : network.example.com
The info I actually require from there are the name field and within the ipv4addrs field is a field called ipv4addr.
Currently I export it all to CSV using this command
$result | Export-Csv -Path C:\Users\neil.bloyce\Documents\2023\2.Feb\InfoBlox.csv
It isn't elegant but gets some of the info I want, however within the ipv4addrs I don't get any info except for System.Object[].
How do I adjust my code so that I can pull the ipv4addr out of ipv4addrs so I can see it in the CSV, Ideally the only info I actually need is dns_name and ipv4addr.
I am not sure how I attach the CSV file.
Kind regards
Use the Select-Object cmdlet to copy and transform only a subset of the properties from the object:
$result |Select-Object Name,#{Name='Addresses';Expression={ $_.ipv4addrs.ipv4addr -join ', ' }} |Export-Csv -Path C:\Users\neil.bloyce\Documents\2023\2.Feb\InfoBlox.csv -NoTypeInformation
Here, we extract the Name property from the original object, and then create a new calculated property that extracts the nested ipv4addr values and joins them together in a single string (thus causing Export-Csv to render the value correctly).
I am new to this Powershell.
I am trying to learn how to modified output.
When I run "Write-output $result | format-list" I have the following output
userDetails : #{id=AA:BB:CC:DD:11:22; connectionStatus=CONNECTED; hostType=WIRELESS;
authType=WPA2/WPA3+802.1x/FT-802.1x}
connectedDevice : {#{deviceDetails=}}
How do I rewrite this output to below using powershell 7.2 ? I would like to have
userDetails :
connectionStatus= CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
connectedDevice :
Thank you for your help.
Note: I'm assuming that you're looking for a friendlier display representation of your data. For programmatic processing, Format-* cmdlets should be avoided, for the reasons explained in this answer.
What you're looking for is for Format-List to work recursively, i.e. to not only list the individual properties and their values for each input object itself, but also for nested objects contained in property values.
Format-List does not support this:
Nested objects are represented by their single-line .ToString() representations.
If they're part of a collection (enumerable), the individual elements' representations are joined with , on a single line, and are enclosed in {...}(!) as a whole. How many elements are shown at most is controlled by the $FormatEnumerationLimit preference variable, which defaults to 4.
However, you can approximate recursive listing behavior with Format-Custom; using a simplified example:
# Nested sample object to format.
[pscustomobject]#{
userDetails = [pscustomobject] #{
id = 'AA:BB:CC:DD:11:22'
connectionStatus= 'CONNECTED'
hostType = 'WIRELESS'
authType = 'WPA2/WPA3+802.1x/FT-802.1x'
}
connectedDevice = '...'
} |
Format-Custom -Depth 1 # use higher -Depth levels for multi-level expansion
Output:
class PSCustomObject
{
userDetails =
[
class PSCustomObject
{
id = AA:BB:CC:DD:11:22
connectionStatus = CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
}
]
connectedDevice = ...
}
Note:
Caveat: If a custom view happens to be defined for a given input object's type via associated formatting data, it is that custom view that Format-Custom will invoke, not the structural representation shown above; however, this is rare ([datetime] is a rare example).
Apart from the output showing the structure recursively, the format differs from that of Format-List as follows:
Complex objects are enclosed in class <typeName> { ... }
Elements of collections (enumerables) each render on their own (group of) line(s), enclosed in [ ... ] overall. However, as with Format-List, the number of elements that are shown at most is limited by $FormatEnumerationLimit.
To prevent excessively nested output, Format-Custom stops recursing at a depth of 5 by default; you can control the recursion depth via the -Depth parameter, 1 meaning that only objects in immediate child properties are expanded.
When the recursion depth limit is reached, non-collection objects are represented by their .ToString() representations, as with Format-List.
Here is some code that produces output close to your desired output:
# Create sample data
$result = [pscustomobject] #{
userDetails = [pscustomobject]#{ id="AA:BB:CC:DD:11:22"; connectionStatus="CONNECTED"; hostType="WIRELESS"; authType="WPA2/WPA3+802.1x/FT-802.1x"}
connectedDevice = [pscustomobject]#{ deviceDetails=$null }
}
# Produce output
"userDetails :"
($result.userDetails |
Format-List -Property connectionStatus, hostType, authType |
Out-String).Trim() -replace '(?m)(?<=^[^:]+):', '='
"`nconnectedDevice :"
# TODO: add similar code as for .userDetails
Output:
userDetails :
connectionStatus = CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
connectedDevice :
Using member access .userDetails to select a child object (similar to Select-Object -ExpandProperty userDetails).
Using Format-List -Property to output a list of the given properties
Using Out-String to create a string from the formatting data that is produced by Format-List. This string looks exactly like the output you normally see on the console.
Use String method .Trim() to remove whitespace (in this case newlines) from the beginning and end.
Use the -replace operator to replace the first : of each line by =. See this regex101 demo for more information.
Below is a snip of my powershell code where my response or my variable($witrevisions) is of type array. I am looking to bind this in a html tag which i have defined in the power shell. As I am very new to coding stuff , I am looking the ways how can I bind array to html tag in best possible way
...continuing my line of code
$response4s = (Invoke-RestMethod -Uri $uriAccount -Method get -Headers $AzureDevOpsAuthenicationHeader).values
$wits = $response4s | where({$_.fields.'System.WorkItemType' -eq 'Task'}) # Only retrieve Tasks
$witrevisions = #()
foreach($wit in $response4s){
$customObject = new-object PSObject -property #{
"Title" = $wit.fields.'System.Title'
"AssignedTo" = $wit.fields.'System.AssignedTo'
}
$witrevisions += $customObject
}
$witrevisions | Select-Object `
Title,
AssignedTo
}
and this the sample response i am getting in $witrevisions which i have exported in text file. its a table with two column one having emails and other having a title name.i have tried to show by giving it a table view for better understanding
Assigned To Title
xyz#outlook.com testingpro
drdr#outlook.com resttesting
and here is the html tag where I trying to bind the $witrevisions.
$DOWNLOAD_PAGE_BODY_CONTENT = "<!DOCTYPE html>
`n<html>
`n<head>
`n <title>Validation</title>
`n</head>
`n<body>
`n
`n<p>Please click the link to download the release.</p>
`n<p></p>
`n<p></p>
`n<p>$witrevisions</p>
`n</body>
`n</html>
`n"
Can someone please tell me how should I do this??
Here is an example of some code that would take your array and emit a table, with an explanation to help you tweak to your specific needs:
"<table><body>$($witrevisions|% {"<tr><td>$($_.Title)</td><td>$($_.AssignedTo)</td></tr>"} )</body></table>"
The double quotes are important because they allow string interpolation (it will replace variables with this value, versus being read a plain text. E.g. '[' + $test + ']' => "[$test]"
If you need to do more complex logic in string interpolation, you can use $(...), the ellipses being regular code.
You can iterate through an array by piping to the ForEach-Object, or it's alias %. All the code in the braces will be executed for each item in the array. The current items is represented by $_.
We're then back to string interpolation and using $(...), which is needed to access the members of the current item.
Note: There are several other ways to accomplish (functionally) the same thing. E.g. foreach(...){} vs |%{...}, so feel free to use a different technique if you are more comfortable with doing something a different way.
Say I have an array of objects:
$a = #(
#{ Name = "A"; Value = "2016-01-02" },
#{ Name = "B"; Value = "2016-01-03" },
#{ Name = "C"; Value = "2016-01-04" }
)
The Value property is currently a String. I want to convert the Value property of each object to a DateTime. I could accomplish this with a for loop, but I was wondering if there is a more direct way to do it.
Yes, calculated properties.
$a | select #{N='Name';E={$_.Name}}, #{N='Value';E={ [datetime]$_.Value }}
This will change data type of the first object Value to datetime.
$a[0].value = [datetime]::ParseExact($a[0].value,'yyyy-MM-dd',$null)
And the loop from here :
foreach ($Obj in $a)
{
$Obj.Value = [datetime]::ParseExact($Obj.value,'yyyy-MM-dd',$null)
}
The #TessellatingHeckler 's answer, which you accepted, is not correct for your question! It is only change the representation of the data in the object, but not converted it as you ask. Even if you save it as a new object (or overwrite the original) this will change the object itself. You can see the difference if you run flowing code:
$b=$a | select #{N='Name';E={$_.Name}}, #{N='Value';E={ [datetime]$_.Value }}
#check the original and converted object
$a|gm
$b|gm
I'm trying to pass an array of custom objects to a function for further processing of these objects.
Here's the function where I create my custom object array:
Function GetNetworkAdapterList
{
# Get a list of available Adapters
$hnet = New-Object -ComObject HNetCfg.HNetShare
$netAdapters = #()
foreach ($i in $hnet.EnumEveryConnection)
{
$netconprop = $hnet.NetConnectionProps($i)
$inetconf = $hnet.INetSharingConfigurationForINetConnection($i)
$netAdapters += New-Object PsObject -Property #{
Index = $index
Guid = $netconprop.Guid
Name = $netconprop.Name
DeviceName = $netconprop.DeviceName
Status = $netconprop.Status
MediaType = $netconprop.MediaType
Characteristics = $netconprop.Characteristics
SharingEnabled = $inetconf.SharingEnabled
SharingConnectionType = $inetconf.SharingConnectionType
InternetFirewallEnabled = $inetconf.InternetFirewallEnabled
SharingConfigurationObject = $inetconf
}
$index++
}
return $netAdapters
}
Then in my main code I call above function like this:
$netAdapterList = GetNetworkAdapterList
The $netAdapterList returns the expected data, and I can do stuff like:
$netAdapterList | fl Name, DeviceName, Guid, SharingEnabled
So far so good.
Now I want to call a function passing in the $netAdapterList
I've created a dummy function like this:
Function ShowAdapters($netAdapterListParam)
{
$netAdapterListParam | fl Name, DeviceName, Guid, SharingEnabled
}
And when I invoke it like this:
ShowAdapters $netAdapterList
Nothing gets printed out.
I've tried changing the function's signature but still no luck:
Function ShowAdapters([Object[]]$netAdapterListParam)
Function ShowAdapters([Object]$netAdapterListParam)
Function ShowAdapters([PSObject[]]$netAdapterListParam)
Function ShowAdapters([array]$netAdapterListParam)
Anybody knows what I'm doing wrong? How can I get to my custom objects inside the function?
Thanks for your reply #Christian. Tried your steps, copy pasting bits and pieces into the shell and it indeed worked. However If i run the full .ps1 script is not printing out anything.
I've run the script in Powershell IDE setting breakpoints inside the ShowAdapters function, and $netAdapterListParam has indeed the expected custom objects array I'm passing in, so I've narrowed down the issue to be in the FL commandlet.
For some reason $netAdapterList | fl Name, DeviceName, Guid, SharingEnabled did not work for me, so I ended up using the following instead:
$formatted = $netAdapterListParam | fl Name, DeviceName, Guid, SharingEnabled | Out-String
Write-Host $formatted
That did the trick and the 4 properties were printed on the screen.
Lessons learned:
1) The Powershell IDE built into Win7 can be a very useful tool for debugging scripts
2) Format-List can be quirky when formatting custom objects, so Out-String was required.