Home > Software design >  How can I go about parsing this .txt file into a .Json file?
How can I go about parsing this .txt file into a .Json file?

Time:07-21

I've spent all day trying to figure this out, any help would be great! This is the text I want to parse into Json:

============ Get Mouse Position  ===============
    Get Mouse Position
    GetMousePos
    Get the mouse position first
        Command one
        Command two
        Command three
============ Set Mouse Position  ===============
    Set Mouse Position
    SetMousePos
    Set the mouse position after
        Command one
        Command two
        Command three

The Json output I am aiming for is:

{

  "Get Mouse Position": {

    "Trigger": "GetMousePos",

    "Description": "Get the mouse position first",

    "body": [

      "Command one",

      "Command two",

      "Command three"

    ]

  },

  "Set Mouse Position": {

    "Trigger": "SetMousePos",

    "Description": "Set the mouse position after",

    "body": [

      "Command one",

      "Command two",

      "Command three"

    ]

  },

}

I've been doing allot of reading and experimenting but I just cant seem to figure it out. the ConvertFrom-StringData command gets me mostly there but it does not seem to support arrays for a single key (for command one, two, three section).

I tried to experimenting with PSCustomObject and ConvertTo-Json like below and it gives me perfect Json output but I cant wrap my head around how to properly code my data into the example below for every potential ===== [Object] ==== section there could be.

$myObject = [PSCustomObject]@{

    'Get Mouse Position' = [ordered]@{

        Trigger = 'GetMousePos'

        Description = 'Get the mouse position first'

            body = @(

            'Command one'

            'Command two'

            'Command three'

            )

        }

  

        'Set  Mouse Position' = [ordered]@{

            Trigger = 'Set MousePos'

            Description = 'Set  the mouse position last'

                body = @(

                'Command one'

                'Command two'

                'Command three'

                )

            }

}

I would really like to know some potential ways I can approach this, that would be so wonderful. Also, a related question. Does the ConvertFrom-StringData command not support multiple values/arrays for a single key? Thanks allot

PS: I have taken the liberty to also ask this question in other communities.

CodePudding user response:

Ok, since I already did the work I'll go off the assumption that the records are split by the ====== lines, and that within a record the first line denotes the title, the second the trigger, the third the description, and the rest is the body. My suggestion is to read the whole file in as a multi-line string, split on the === lines, and pass to a ForEach-Object loop. For the beginning of the loop define an empty object, and for each record passed split it on line breaks into 4 things, and setup your hashtable from that split, and add a property to the object based off that info as well. At the end of the loop output your object that now has a bunch of properties, and pass it to convertto-json.

(Get-Content MyFile.txt -Raw) -split '(?ms)=. ?[\r\n] '|
    ForEach-Object -begin {
        $MyObj=New-Object PSObject
    } -process {
        $Split=$_ -split '[\r\n] ',4;
        $ThisVal = [ordered]@{
            Trigger=$Split[1].trim();
            Description=$Split[2].trim();
            Body=$Split[3] -split '[\r\n] ' -replace '^\s*|\s*$'
        };
        Add-Member -InputObject $MyObj -NotePropertyName $Split[0].Trim() -NotePropertyValue $ThisVal
    } -end {
        $MyObj
    }|convertto-json

CodePudding user response:

# Initialize an ordered hashtable.
$oht = [ordered] @{}

# Split the input file into blocks of lines, not including the header
# (separator) lines.
(Get-Content -Raw file.txt) -split '(?m)^===.*\r?\n' -ne '' | ForEach-Object {
  # Parse the block of lines into individual lines
  $name, $trigger, $description, $body = $_ -replace '\r?\n\z' -split '\r?\n'
  # Add an entry to the ordered hashtable.
  $oht[$name.Trim()] = [ordered] @{
      Trigger = $trigger.Trim()
      Description = $description.Trim()
      body = $body.Trim()
    }
  }

# Convert the resulting ordered hashtable to JSON
$oht | ConvertTo-Json

Note: The above uses a nested [ordered] hashtable instead of a nested [pscustomobject], as that is sufficient for to-JSON conversion and makes iterative construction easier (while also being more light-weight).
If a nested [pscustomobject] instance is desired, replace [ordered] inside the ForEach-Object script block with [pscustomobject] for the nested instance, and then use [pscustomobject] $oht to construct the outer instance.

See also:

  • Related