skip to Main Content

I work with Powershell 5.1
I try to use a (simple) JSON-File as a letter box between scripts.
So at the beginning of the script I read the File, modify it and store it at the end.
For Example the following file

{
    "A":  {
              "April":  "4",
              "August":  "8"
          },
    "J":  {
              "January":  "1",
              "July":  "7"
          }
}

For better handling I wrote a Read-Value and a Write-Value function. In this Example the Read-Value shows my problem: the function doesn’t find the Parameter "Name".

$config_file_full = Join-Path -Path $PSScriptRoot -ChildPath 'months.json'
$config_json = Get-Content -Raw -Path $config_file_full | ConvertFrom-Json

function Read-Value {
    param (
        [string]$Subject,
        [string]$Name
    )
    # $result = $null

    if (-not ($config_json.PSObject.Properties.Name -contains $Subject)) {
        Write-Host "READ NO MATCH for SUBJECT " $Subject
        $result = $null
    } elseif (-not ($config_json.PSObject.Properties.$Subject.Name -contains $Name)) {
        Write-Host "READ NO MATCH FOR SUBJECT " $Subject "NAME " $Name
        $result = $null
    } else {
        $result = $config_json.$Subject.$Name
        Write-Host "READ NO MATCH FOR SUBJECT " $Subject "NAME " $Name "VALUE <" $result ">"
    }

    return $result
}

$a = Read-Value -Subject 'A' -Name 'April'
Write-Host "<" $a ">"

$config_json | ConvertTo-Json | Set-Content -Path $config_file_full

The Result is

READ NO MATCH FOR SUBJECT  A NAME  April
<  >

What is wrong? The elseif- Condition does’t work as expected.
Thank you

2

Answers


  1. There are a few issues here.

    • PSObject.Properties here is a PSNoteProperty type, which doesn’t allow you to address the properties using dot-notation.
    • Even when you grab the $Subject you want to check, the Name property contains the name of that Subject and not the $Name you were checking for

    This should work better:

    function Read-Value {
        param (
            [string]$Subject,
            [string]$Name
        )
        if (-not ($config_json.PSObject.Properties.Name -contains $Subject)) {
            Write-Host "READ: No match for SUBJECT '$($Subject)'"
        } elseif (-not ($config_json.PSObject.Properties[$Subject].Value.PSObject.Properties.Name -contains $Name)) {
            Write-Host "READ: Matched Subject '$($Subject)' but not Name '$($Name)'"
        } else {
            Write-Host "READ: Matched Subject '$($Subject)' and Name '$($Name):<$($result)>"
            $config_json.$Subject.$Name
        }
    }
    
    Login or Signup to reply.
  2. James Ruskin’s answer will solve your problem, but it can be done a little more elegantly if you replace your if/elseif/else statement with 2 separate if blocks:

    function Read-Value {
        param (
            [string]$Subject,
            [string]$Name
        )
        if (-not ($config_json.PSObject.Properties.Name -contains $Subject)) {
            Write-Host "READ: No match for SUBJECT '$($Subject)'"
            return
        }
    
        # if we've reached this point it must mean the subject exists, assign to a variable
        $subjectObject = $config_json.PSObject.Properties[$Subject].Value
    
        if (-not ($subjectObject.PSObject.Properties.Name -contains $Name)) {
            Write-Host "READ: Matched Subject '$($Subject)' but not Name '$($Name)'"
            return
        }
    
        Write-Host "READ: Matched Subject '$($Subject)' and Name '$($Name):<$($result)>"
        $config_json.$Subject.$Name
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search