2

I'm having a little trouble finding the index of a hashtable in an array. I create a JSON with this code:

$start = {
Clear-Host
$BIB = Read-Host 'Bibliothek'
$BIBName = Read-Host 'Bibliothek Name'
$Standort = Read-Host 'Bibliothek Standort'
$Autor = Read-Host 'Buchautor'
$BuchName = Read-Host 'Buchname'

$jsonfile = "C:\Skripte\bibV2-1000.xml"
if(![System.IO.File]::Exists($jsonfile)){
    $Data = @{BIBs = @(
        @{$BIB = @{BIBName=$BIBName}, 
        @{Standort = $Standort}, 
        @{Bücher = @(
            @{BuchName = $BuchName; 
            Autor = $Autor})
        }}
    )}
    ConvertTo-Json -Depth 50 -InputObject $Data | Add-Content $jsonfile
    .$continue
} else {
        $jsonfile = "C:\Skripte\bibV2-1000.json"
        $Data = Get-Content $jsonfile | ConvertFrom-Json
        $Data.BIBs += New-Object -TypeName psobject -Property @{$BIB = 
               @{BIBname=$BIBName},
               @{Standort=$Standort},
               @{Bücher = @(@{
                    Buchname=$BuchName;
                    Autor=$Autor})
               }
        }
        ConvertTo-Json -Depth 50 -InputObject $Data | Out-File $jsonfile}
        .$continue
}


$continue = {
Write-Host ""
Write-Host "Was wollen Sie machen?"
Write-Host "(1) Eine weitere Bibliothek hinzufügen"
Write-Host "(2) Einer Bibliothek neue Bücher hinzufügen"
Write-Host "(E) Script beenden"

    If (($read = Read-Host ) -eq "1") {
    &$start} else {
            if (($read) -eq "2") {
                . C:\Skripte\büc.ps1 } else {
                    if (($read) -eq "E") {
                        exit} else {
                            Write-Host "+++ FALSCHE EINGABE! Bitte wählen Sie (1) oder (2) für die entsprechende Aktion +++"
                            .$continue
                        }
                }
    }
}
&$start

The output is as follows:

{
    "BIBs": [{
        "BIB1": [{
            "BIBName": "123"
        },
            {
                "Standort": "123"
            },
            {
                "Bücher": [{
                    "Autor": "123",
                    "BuchName": "123"
                }]
            }
        ]
    },
        {
            "BIB2": [{
                "BIBname": "345"
            },
                {
                    "Standort": "345"
                },
                {
                    "Bücher": [{
                        "Autor": "345",
                        "Buchname": "345"
                    }]
                }
            ]
        }
    ]
}

Now I want to find out the index of "BIB1". I already tried the IndexOf()-Method which should create the output "0" but it gives me "-1" instead, because it can't find the value. How can I get the index of "BIB1"?

12
  • 1
    can you show the objects you are working with? this just looks like a json object Commented Mar 20, 2018 at 11:46
  • Please edit your question with this information. Reading code in comments sucks... Commented Mar 20, 2018 at 12:15
  • 1
    So. One thing about ConvertTo-Json is that it doesn't make a "Json Object". It just creates a Json formatted string. If you want a structured data object that you can easily manipulate and poke around in I would suggest either leaving it as a hash of arrays and hashes as you had it before you converted it or converting it to XML. Commented Mar 20, 2018 at 12:23
  • I already tried it without converting it to json, but the output of IndexOf() is still "-1" Commented Mar 20, 2018 at 12:42
  • Already tried what? Already tried how? What code did you try with? Commented Mar 20, 2018 at 12:43

2 Answers 2

2

Judging by your earlier question, you're attempting to get the index of a specific object so you can access it via its containing array. However, you can do this more directly: $objOfInterest = $Data.BIBs | ? BIB1 - see my answer to your earlier question for details.

You need to iterate over the array elements of $Data.BIBs, which - on reading your serialized-to-a-file-as-JSON hashtables back in with ConvertFrom-Json - are custom objects (as Ansgar correctly points out; they are instances of [System.Management.Automation.PSCustomObject]), and check each for the presence of property 'BIB1':

  • (In a hashtable, you'd check for the presence of key 'BIB1' with .ContainsKey('BIB1'))

  • To test the existence of an object property, you need reflection, which is most easily - but somewhat obscurely - achieved via the hidden .PSObject property, as demonstrated in Ansgar Wiechers' more elegant solution.

However, given that the properties of interest have nonempty values, we can infer from the presence of a nonempty value that a given property exists, using implicit Boolean (logic): $obj.'BIB1' by default returns $null if there is no BIB1 property, which is "falsy" in a Boolean context such as an if conditional; conversely, any nonempty value is "truthy":

$propName = 'BIB1'
$i = $ndx = -1
foreach ($obj in $Data.BIBs) {
  ++$i
  if ($obj.$propName) { $ndx = $i; break}
}
$ndx  # $ndx now contains the index of the target object or -1 if there was no match
Sign up to request clarification or add additional context in comments.

Comments

2

$Date.BIBs is an array of custom objects, not hashtables (since you wrote your original data to a JSON file and then converted that back), so you need something like this:

$arr = $Data.BIBs | ForEach-Object { $_.PSObject.Properties.Name }
$arr.IndexOf('BIB1')  # returns 0
$arr.IndexOf('BIB2')  # returns 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.