Skip to content

Instantly share code, notes, and snippets.

@daniel0x00
Last active July 27, 2021 14:56
Show Gist options
  • Save daniel0x00/15f8871f2c0aca803e7f60ae0a1f42c1 to your computer and use it in GitHub Desktop.
Save daniel0x00/15f8871f2c0aca803e7f60ae0a1f42c1 to your computer and use it in GitHub Desktop.
PowerShell function that converts a PowerShell Object into a DotNotation object
function ConvertTo-DotNotation {
# PowerShell cmdlet that converts a PowerShell/JSON object into a dot.notation array.
# For Splunk use cases, this cmdlet enables data to be TERM() and PREFIX() ready.
# Author: Daniel Ferreira (@daniel0x00)
# License: BSD 3-Clause
# Source: https://gist.github.com/daniel0x00/15f8871f2c0aca803e7f60ae0a1f42c1
# Note: any improvement opportunity to make this function "a 1-liner" producing same results is very welcomed.
# TODO: Support for Dictionary object.
# In the meantime, Dictionaries must be casted into PSCustomObject like this: [PSCustomObject][Hashtable]$object
<#
.SYNOPSIS
Converts a JSON object into a dot.notation array. It is required to first convert the json string into a PSCustomObject.
.EXAMPLE
@'
{
"nmaprun": {
"scanner": "nmap",
"args": "./nmap -T4 -F --open -oX - --stats-every 200ms 10.0.0.0/24",
"start": "1587811935",
"version": "7.80",
"scaninfo": {
"type": "syn",
"protocol": "tcp",
"numservices": "100",
},
"host": [
{
"starttime": "1587811936",
"endtime": "1587811940",
"status": {
"state": "up",
"reason": "echo-reply",
"reason_ttl": "247"
}
}
]
}
}
'@ | ConvertFrom-Json | ConvertTo-DotNotation
# Result:
nmaprun.scanner=nmap
nmaprun.args=./nmap -T4 -F --open -oX - --stats-every 200ms 10.0.0.0/24
nmaprun.start=1587811935
nmaprun.version=7.80
nmaprun.scaninfo.type=syn
nmaprun.scaninfo.protocol=tcp
nmaprun.scaninfo.numservices=100
nmaprun.host.1.starttime=1587811936
nmaprun.host.1.endtime=1587811940
nmaprun.host.1.status.state=up
nmaprun.host.1.status.reason=echo-reply
nmaprun.host.1.status.reason_ttl=247
.EXAMPLE
Resolve-DnsName -Name splunk.com | Select-Object *, @{n='dotnotation';e={$_ | ConvertTo-DotNotation}} | ConvertTo-Json
# Result:
[
{
"Address": "52.5.196.118",
"IPAddress": "52.5.196.118",
"QueryType": 1,
"IP4Address": "52.5.196.118",
"Name": "splunk.com",
"Type": 1,
"CharacterSet": 1,
"Section": 1,
"DataLength": 4,
"TTL": 18,
"dotnotation": [
"Address=52.5.196.118",
"IPAddress=52.5.196.118",
"QueryType=A",
"IP4Address=52.5.196.118",
"Name=splunk.com",
"Type=A",
"CharacterSet=Unicode",
"Section=Answer",
"DataLength=4",
"TTL=18"
]
},
{
"Address": "35.153.82.195",
"IPAddress": "35.153.82.195",
"QueryType": 1,
"IP4Address": "35.153.82.195",
"Name": "splunk.com",
"Type": 1,
"CharacterSet": 1,
"Section": 1,
"DataLength": 4,
"TTL": 18,
"dotnotation": [
"Address=35.153.82.195",
"IPAddress=35.153.82.195",
"QueryType=A",
"IP4Address=35.153.82.195",
"Name=splunk.com",
"Type=A",
"CharacterSet=Unicode",
"Section=Answer",
"DataLength=4",
"TTL=18"
]
}
]
.PARAMETER InputObject
PSCustomObject. Mandatory. Pipeline enabled.
The input JSON passed as PSCustomObject.
#>
[CmdletBinding()]
[OutputType([System.Array])]
param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
[PSCustomObject] $InputObject,
[Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$false)]
[string] $Parent=''
)
begin { $name = ''; }
process {
foreach ($item in $InputObject.PSObject.Properties) {
$name += "$Parent$($item.Name)"
# Match everything but objects
if (($item.TypeNameOfValue -notmatch 'Object') -and ($item.TypeNameOfValue -notmatch 'Microsoft.PowerShell') -and ($item.TypeNameOfValue -notmatch 'Selected.System')) {
# Match string array:
if ($item.TypeNameOfValue -match 'String\[\]$') {
# Output:
if ($item.Value.Length -eq 1) {
"{0}={1}" -f $name, $item.Value[0] #-replace ' ','__' -replace ',','___'
#$output
$name = ''
}
else {
for ($x=0; $x -lt $item.Value.Length; $x++) {
"{0}={1}" -f "$name.$($x+1)", $item.Value[$x] #-replace ' ','__' -replace ',','___'
#$output
}
$name = ''
}
}
# Match any other type of object that can be converted into text:
else {
# Output:
"{0}={1}" -f $name, $item.Value #-replace ' ','__' -replace ',','___'
#$output
$name = ''
}
}
# Match null values:
elseif (($null -eq $item.Value) -or ($item.Value.Count -eq 0)) {
# Output:
"{0}=null" -f $name
$name = ''
}
# Match array:
elseif ($item.TypeNameOfValue -match 'Object\[\]') {
# Output:
$objectType = $item.Value[0].GetType()
if ($objectType -match 'Object') {
$Parent = $name
for ($x=0; $x -lt $item.Value.Length; $x++) {
#$name = "$Parent.$($x+1)."
#$child = $item.Value[$x]
ConvertTo-DotNotation -Input ($item.Value[$x]) -Parent ("$Parent.$($x+1).")
}
$Parent = $Parent -replace '\.\w+$','.' -replace ($name -replace '\.[\d]+\.',''),''
$name = ''
}
else {
if ($item.Value.Length -eq 1) {
"{0}={1}" -f $name, $item.Value[0] #-replace ' ','__' -replace ',','___'
#$output
$name = ''
}
else {
for ($x=0; $x -lt $item.Value.Length; $x++) {
"{0}={1}" -f "$name.$($x+1)", $item.Value[$x] #-replace ' ','__' -replace ',','___'
#$output
}
$name = ''
}
}
}
# Match objects:
else {
ConvertTo-DotNotation -Input $item.Value -Parent "$name."
$name = ''
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment