# Based on v 1.7 of the JSON_1.7.psm1 from
#
# > $Json = Get-Process |
# >> Select PM, WS, CPU, ID, ProcessName, @{n="SnapshotTime";e={Get-Date}} |
# >> ConvertTo-Json -NoType
#
# > $Json | ConvertFrom-json -Type PSObject
try {
Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization -ErrorAction "Stop"
} catch {
throw "PXP Agent could not load the assemblies needed for JSON parsing. Please install .NET Framework 3.5 or greater, or rewrite the task to use a different input method than 'powershell'."
}
$utf8 = [System.Text.Encoding]::UTF8
function Write-Stream {
PARAM(
[Parameter(Position=0)] $stream,
[Parameter(ValueFromPipeline=$true)] $string
)
PROCESS {
$bytes = $utf8.GetBytes($string)
$stream.Write( $bytes, 0, $bytes.Length )
}
}
function Convert-JsonToXml {
PARAM([Parameter(ValueFromPipeline=$true)] [string[]] $json)
BEGIN {
$mStream = New-Object System.IO.MemoryStream
}
PROCESS {
$json | Write-Stream -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()
}
}
}
Function ConvertFrom-Xml {
[CmdletBinding(DefaultParameterSetName="AutoType")]
PARAM(
[Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=1)] [Xml.XmlNode] $xml,
[Parameter(Mandatory=$true,ParameterSetName="ManualType")] [Type] $Type,
[Switch] $ForceType
)
PROCESS{
if (Get-Member -InputObject $xml -Name root) {
return $xml.root.Objects | ConvertFrom-Xml
} elseif (Get-Member -InputObject $xml -Name Objects) {
return $xml.Objects | ConvertFrom-Xml
}
$propbag = @{}
foreach ($name in Get-Member -InputObject $xml -MemberType Properties | Where-Object{$_.Name -notmatch "^(__.*|type)$"} | Select-Object -ExpandProperty name) {
Write-Debug "$Name Type: $($xml.$Name.type)" -Debug:$false
$propbag."$Name" = Convert-Properties $xml."$name"
}
if (!$Type -and $xml.HasAttribute("__type")) { $Type = $xml.__Type }
if ($ForceType -and $Type) {
try {
$output = New-Object $Type -Property $propbag
} catch {
$output = New-Object PSObject -Property $propbag
$output.PsTypeNames.Insert(0, $xml.__type)
}
} elseif ($propbag.Count -ne 0) {
$output = New-Object PSObject -Property $propbag
if ($Type) {
$output.PsTypeNames.Insert(0, $Type)
}
}
return $output
}
}
Function Convert-Properties {
PARAM($InputObject)
switch ($InputObject.type) {
"object" {
return (ConvertFrom-Xml -Xml $InputObject)
}
"string" {
$MightBeADate = $InputObject.get_InnerText() -as [DateTime]
## Strings that are actually dates (*grumble* JSON is crap)
if ($MightBeADate -and $propbag."$Name" -eq $MightBeADate.ToString("G")) {
return $MightBeADate
} else {
return $InputObject.get_InnerText()
}
}
"number" {
$number = $InputObject.get_InnerText()
if ($number -eq ($number -as [int])) {
return $number -as [int]
} elseif ($number -eq ($number -as [double])) {
return $number -as [double]
} else {
return $number -as [decimal]
}
}
"boolean" {
return [bool]::parse($InputObject.get_InnerText())
}
"null" {
return $null
}
"array" {
[object[]]$Items = $(foreach( $item in $InputObject.GetEnumerator() ) {
Convert-Properties $item
})
return $Items
}
default {
return $InputObject
}
}
}
Function ConvertFrom-Json2 {
[CmdletBinding()]
PARAM(
[Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=1)] [string] $InputObject,
[Parameter(Mandatory=$true)] [Type] $Type,
[Switch] $ForceType
)
PROCESS {
$null = $PSBoundParameters.Remove("InputObject")
[Xml.XmlElement]$xml = (Convert-JsonToXml $InputObject).Root
if ($xml) {
if ($xml.Objects) {
$xml.Objects.Item.GetEnumerator() | ConvertFrom-Xml @PSBoundParameters
} elseif ($xml.Item -and $xml.Item -isnot [System.Management.Automation.PSParameterizedProperty]) {
$xml.Item | ConvertFrom-Xml @PSBoundParameters
} else {
$xml | ConvertFrom-Xml @PSBoundParameters
}
} else {
Write-Error "Failed to parse JSON with JsonReader" -Debug:$false
}
}
}
function ConvertFrom-PSCustomObject
{
PARAM([Parameter(ValueFromPipeline = $true)] $InputObject)
PROCESS {
if ($null -eq $InputObject) { return $null }
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
$collection = @(
foreach ($object in $InputObject) { ConvertFrom-PSCustomObject $object }
)
$collection
} elseif ($InputObject -is [System.Management.Automation.PSCustomObject]) {
$hash = @{}
foreach ($property in $InputObject.PSObject.Properties) {
$hash[$property.Name] = ConvertFrom-PSCustomObject $property.Value
}
$hash
} else {
$InputObject
}
}
}
function Get-ContentAsJson
{
[CmdletBinding()]
PARAM(
[Parameter(Mandatory = $true)] $Text,
[Parameter(Mandatory = $false)] [Text.Encoding] $Encoding = [Text.Encoding]::UTF8
)
# using polyfill cmdlet on PS2, so pass type info
if ($PSVersionTable.PSVersion -lt [Version]'3.0') {
$Text | ConvertFrom-Json2 -Type PSObject | ConvertFrom-PSCustomObject
} else {
$Text | ConvertFrom-Json | ConvertFrom-PSCustomObject
}
}
function ConvertTo-String
{
[CmdletBinding()]
PARAM([Parameter(Mandatory = $True, ValueFromPipeline = $True)] $Object)
BEGIN {
$outputs = @()
}
PROCESS {
if ($Object -is [Hashtable]) {
$outputs += (HashtableTo-String $Object)
} else {
$outputs += $Object
}
} end {
$outputs -join "`n"
}
}
function HashtableTo-String
{
[CmdletBinding()]
PARAM([Parameter(Mandatory = $True, ValueFromPipeline = $True)] [Hashtable] $Hashtable)
($Hashtable.GetEnumerator() | % { "$($_.Key): $($_.Value)" }) -join "`n"
}
Copyright 2K16 - 2K18 Indonesian Hacker Rulez