Home > Software engineering >  PowerShell Here-String to Json
PowerShell Here-String to Json

Time:11-03

I'm attempting to convert a PowerShell Here-String to a Json file. This is a sample size of what I need to convert. I will be needing to convert a few dozen override files that can be quite long and doing this manually is not how I want to accomplish this.

$a = @'
override['abc_os_config']['local_administrators']['default_administrators']['abc.com'] = %w {}
override['abc_os_config']['local_administrators']['default_administrators']['devad.abc.com'] = %w {}
override['abc_os_config']['local_administrators']['default_administrators']['qad.abc.com'] = %w {}
override['CIS_Remediation_Windows']['security_options']['lanman_authentication_level'] = 3
'@

$b = $a.Replace('override', '').Replace("'", '').Replace('[', '\').Replace(']', '').Replace(' =',':')

$b.Split('\') | ConvertTo-Json -Depth 100

What is generated:

[
  "",
  "abc_os_config",
  "local_administrators",
  "default_administrators",
  "abc.com: %w {}\n",
  "abc_os_config",
  "local_administrators",
  "default_administrators",
  "devad.abc.com: %w {}\n",
  "abc_os_config",
  "local_administrators",
  "default_administrators",
  "qad.abc.com: %w {}\n",
  "CIS_Remediation_Windows",
  "security_options",
  "lanman_authentication_level: 3"
]

What should be generated:

{
  "abc_os_config": {
    "local_administrators": {
      "default_administrators": {
        "abc.com": "%w {}",
        "devad.abc.com": "%w {}",
        "qad.abc.com": "%w {}"
      }
    }
  },
  "CIS_Remediation_Windows": {
    "security_options": {
      "lanman_authentication_level": "3"
    }
  }
}

CodePudding user response:

Here is a solution using my function Set-TreeValue, after some preprocessing of the original data:

# Create sample input
$a = @'
override['abc_os_config']['local_administrators']['default_administrators']['abc.com'] = %w {}
override['abc_os_config']['local_administrators']['default_administrators']['devad.abc.com'] = %w {}
override['abc_os_config']['local_administrators']['default_administrators']['qad.abc.com'] = %w {}
override['CIS_Remediation_Windows']['security_options']['lanman_authentication_level'] = 3
'@ 

# Split input text into an array of lines
$textLines = $a -split '\r?\n'

# Create an ordered hashtable
$result = [ordered] @{}

foreach( $line in $textLines ) {
    # Split current line into path and value
    $path, $value = $line -split "'\]\s*=\s*"

    # Remove unwanted stuff from the path
    $path = $path -replace "override\['"
    
    # Add current value to the tree, creating any nested hashtables as necessary
    Set-TreeValue -HashTable $result -Path $path -Value $value -PathSeparator "'\]\['"
}

# Specify a large enough depth as default value of 2 would skip deeper nested data
$result | ConvertTo-Json -Depth 99

Output:

{
  "abc_os_config": {
    "local_administrators": {
      "default_administrators": {
        "abc.com": "%w {}",
        "devad.abc.com": "%w {}",
        "qad.abc.com": "%w {}"
      }
    }
  },
  "CIS_Remediation_Windows": {
    "security_options": {
      "lanman_authentication_level": "3"
    }
  }
}

How each line is processed:

E. g. taking the line

override['abc_os_config']['local_administrators']['default_administrators']['abc.com'] = %w {}
  • Split current line into path and value:
    $path = "override['abc_os_config']['local_administrators']['default_administrators']['abc.com"
    $value = "%w {}"
    
  • Remove unwanted stuff from the path:
    $path = "abc_os_config']['local_administrators']['default_administrators']['abc.com" 
    
  • In Set-TreeValue:
    • Split path into components, using '][' as separator (backslash-escaped because the function expects a RegEx)
      abc_os_config
      local_administrators
      default_administrators
      abc.com
      
    • Create any nested hashtable(s) and assign the value
  • Related