Search code examples
jsonpowershell-7.0

Powershell Parse Swagger Json


The following works to parse a Swagger json into resource, method, httptype but probably... the $path.Definition part is weirdly, how can i get $path.Definition to be an array not a string that i need to parse for the array symbol.

$json = Get-Content -Path "$PSScriptRoot/Test/example_swagger.json" | ConvertFrom-Json
$paths = Get-Member -InputObject $json.paths -MemberType NoteProperty
$result = ""
foreach($path in $paths) {
    $elements = $path.Name.Substring(5).split("/") -join ","
    $httpmethods = $path.Definition.Substring($path.Definition.IndexOf("@{"))
    if ($httpmethods.Contains("get")) {
        $result += $elements + ", GET" + "`n"
    }
    if ($httpmethods.Contains("post")) {
        $result += $elements + ", POST" + "`n" #same methodnames different http methods
    }
}
$result

Solution

  • As detailed in my answer to Iterating through a JSON file PowerShell, the output of ConvertFrom-Json is hard to iterate over. This makes "for each key in object" and "keys of object not known ahead of time" kinds of situations more difficult to handle, but not impossible.

    You need a helper function:

    # helper to turn PSCustomObject into a list of key/value pairs
    function Get-ObjectMember {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
            [PSCustomObject]$obj
        )
        $obj | Get-Member -MemberType NoteProperty | ForEach-Object {
            $key = $_.Name
            [PSCustomObject]@{Key = $key; Value = $obj."$key"}
        }
    }
    

    with this, the approach gets a whole lot simpler:

    $swagger = Get-Content -Path "example_swagger.json" -Encoding UTF8 -Raw | ConvertFrom-Json
    
    $swagger.paths | Get-ObjectMember | ForEach-Object {
        [pscustomobject]@{
            path = $_.Key
            methods = $_.Value | Get-ObjectMember | ForEach-Object Key
        }
    }
    

    Applied to the default Swagger file from https://editor.swagger.io/ as a sample, this is printed

    path                     methods            
    ----                     -------            
    /pet                     {post, put}        
    /pet/findByStatus        get                
    /pet/findByTags          get                
    /pet/{petId}             {delete, get, post}
    /pet/{petId}/uploadImage post               
    /store/inventory         get                
    /store/order             post               
    /store/order/{orderId}   {delete, get}      
    /user                    post               
    /user/createWithArray    post               
    /user/createWithList     post               
    /user/login              get                
    /user/logout             get                
    /user/{username}         {delete, get, put}