json_decode access nested array with multiple identical keys - arrays

I am trying to access a specific value from an array, but have difficulties fetching it. More specifically it is the value DealerCarExtended-->ImageIds-->ImageId-->Id, but my problem is that ImageIds is an array with multiple ImageId's. I use son_decode, but the code below obviously doesn't work.
$response = file_get_contents( 'http://api.autoit.dk/car/GetCarsExtended/391B093F-BB4A-45AA-BEFF-7B33842401EA' );
$myArray = json_decode($response,true);
$myArray = $myArray[0];
echo $myArray['ImageIds']['ImageId']['Id'];
I'm sure that this is trivial for most of you guys but i'm a newbie in this :-)

A working example :
$response = file_get_contents( 'http://api.autoit.dk/car/GetCarsExtended/391B093F-BB4A-45AA-BEFF-7B33842401EA' );
$myArray = json_decode($response,true);
$myArray = $myArray[0];
# fetching second array item :
echo $myArray['ImageIds'][1]['Id']

Related

How do multidimensional-arrays work in PowerShell?

I'm currently trying to create a program to train a foreign language.
For that i have two single dimensional array. In the first one i store all the foreign syllables or words and in the second one i'm storing the answers in my native language:
$QuestionArray = New-Object System.Collections.ArrayList
$QuestionArray = "Word1","Word2","Word3"
$AnswerArray = New-Object System.Collections.ArrayList
$AnswerArray = "Answer1","Answer2","Answer3"
Afterwards i check if the entered value is inside the answer-array. If it is i select the index and the index of the randomly selected word from the question-array. If both indexes match then the question has been answered correct otherwise its wrong.
$RandomQuestion = $QuestionArray | Get-Random
$Answer = $InputTextbox.Text
$IndexPositionQuestion = [array]::indexof($QuestionArray, $RandomQuestion)
$IndexPositionAnswer = [array]::indexof($AnswerArray, $Answer)
If($IndexPositionAnswer -eq $IndexPositionQuestion){
$RightTextbox.Text = $script:countercorrect++
}else{
$WrongTextbox.Text = $script:counterwrong++
}
The program works as intended but when i showed it to a colleague today he just told me that the comparing part of the program is coded ugly and is anything but best practice.
How could i go about it in any other way? I read a little bit about multidimensional-arrays but i just can't wrap my head around it. How would i benefit from multidimensional-arrays? How could i select the value i need from it to display, compare, check and so on?
Before digging into multidimensional arrays, why dont you try something like an array with hashtables?
$array = #(
#{
Question = 'blah?'
Answer = 'blub'
},
#{
Question = 'james'
Answer = 'Dean'
}
)
You can reference the values by
for($i = 0; $i -lt $array.Count; $i++){
$array[$i].Question
$array[$i].Answer
}
in youre example try something like
$RandomQuestionNr = 0..($QuestionArray.count -1) | Get-Random
$Answer = $InputTextbox.Text
if($array[$RandomQuestionNr].answer -eq $Answer){
$RightTextbox.Text = $script:countercorrect++
}else{
$WrongTextbox.Text = $script:counterwrong++
}

Strange behaviour with strings and arrays

Here I assign the value of an array to a variable, I then alter the variable, the array changes also.
$TestArray = #{ "ValueA" = "A" ; "ValueB" = "B" ; "Number" = "" }
$TestNumbers = 1..10
foreach ($number in $testnumbers) {
$results = $TestArray
$results.Number = $number
Write-Host $TestArray.Number
}
I thought that $results = $TestArray would take a copy of $TestArray but this test shows that modifying $results also changes the corresponding value in $TestArray
Can anyone help me understand this behavior?
Doing:
$results = $TestArray
will make $results a reference to the same object referred to by TestArray. So, if you change one, the other will also be affected because they are the same object.
To instead make $results a copy of $TestArray, you can use its Clone method:
$results = $TestArray.Clone()
Also, just for the record, $TestArray is not actually an array. It is a hashtable (also called a hashmap) where keys are paired with values. An array would be something like:
$TestArray = (1, 2, 3)

Write session data with dot notation

I add my session variables like this:
foreach ( $data as $key => $value ) {
$this->Session->write("MyVariable.$key", $value );
}
Is it possible to add element to session variable array without passing the key ?
I mean like this:
$MyArray[] = "apple";
$MyArray[] = "banana";
So is it possible to add like this? Pseudo code:
$this->Session->write('MyVariable'.[], "apple");
$this->Session->write('MyVariable'.[], "banana");
Edit: $data array was for giving an example. The data that will be saved is not array. It is a string. Everytime I add to session variable I don't want to give key by code. I wonder whether is it possible out of the box. In my current codes I make it like this:
$newKey = count( $this->Session->read("MyVariable") );
$this->Session->write("MyVariable.$newKey", "apple");
Hi i guess it should be like this:
foreach ( $data as $key => $value ) {
$this->Session->write('MyVariable.'.$key, $value );
}
You have to place a dot inside the quotation mark.
If you don't want to give the key value each time, then store it as an array like #mark said
$this->Session->write("MyVariable", $data);
If you want to add a new value to the $data array in some other part of your code, you'll have to do something like
$data = $this->Session->read("MyVariable");
$data[] = array('other'=>'value');
$this->Session->write("MyVariable", $data);
Or add the exact key like #mmahgoub said
$this->Session->write("MyVariable".$key, $value);

Json decoding arrays [duplicate]

I have a json string like this:
$fields_string = '
{"fields":
{"customers":[{"name":"john","id":"d1"},
{"name":"mike","id":"d2"},
{"name":"andrew","id":"d3"},
{"name":"peter","id":"d4"}]
}
}'
How can I print each name? I will use them later in a html select options, I know how to do that. But I couldn't get the string out.
Here are something I tried:
$obj = json_decode($fields_string);
$fields_detail = $obj-?{"fields"}->{"customers"};
at this point, I am able to print the customer array out by echo json_encode($fields_detail), but before that, I want to get the name break down using foreach. I tried several times, it didn't work. Can anyone help please.
Thanks!
Customers is an array of objects so iterating over each object and reading the property should work.
foreach ($fields_detail as $customer) {
echo $customer->name;
}
Something like this:
$data = json_decode($fields_string, true); // return array not object
foreach($data['fields']['customers'] as $key => $customer) {
echo $customer['name'];
}
Access the names via fields->customers:
$obj = json_decode($fields_string);
foreach($obj->fields->customers as $customer)
{
echo $customer->name . "\n";
}
Demo
foreach($obj->fields->customers as $fields)
echo $fields->name;

PowerShell array unshift

After reading this helpful article on the Windows PowerShell Blog, I realized I could "shift" off the first part of an array, but didn't know how to "unshift" or push elements onto the front of an array in PowerShell.
I am creating an array of hash objects, with the last read item pushed onto the array first. I'm wondering if there is a better way to accomplish this.
## Create a list of files for this collection, pushing item on top of all other items
if ($csvfiles[$collname]) {
$csvfiles[$collname] = #{ repdate = $date; fileobj = $csv }, $csvfiles[$collname] | %{$_}
}
else {
$csvfiles[$collname] = #{ repdate = $date; fileobj = $csv }
}
A couple of things to note:
I need to unroll the previous array element with a foreach loop %{$_}, because merely referencing the array would create a nested array structure. I have to have all the elements at the same level.
I need to differentiate between an empty array and one that contains elements. If I attempt to unroll an empty array, it places a $null element at the end of the array.
Thoughts?
PS: The reason the empty hash element produces a NULL value is that $null is treated as a scalar in PowerShell. For details, see https://connect.microsoft.com/PowerShell/feedback/details/281908/foreach-should-not-execute-the-loop-body-for-a-scalar-value-of-null.
ANSWER:
Looks like the best solution is to pre-create the empty array when necessary, rather than code around the $null issue. Here's the rewrite using a .NET ArrayList and a native PoSh array.
if (!$csvfiles.ContainsKey($collname)) {
$csvfiles[$collname] = [System.Collections.ArrayList]#()
}
$csvfiles[$collname].insert(0, #{ repdate = $repdate; fileobj = $csv })
## NATIVE POSH SOLUTION...
if (!$csvfiles.ContainsKey($collname)) {
$csvfiles[$collname] = #()
}
$csvfiles[$collname] = #{ repdate = $repdate; fileobj = $csv }, `
$csvfiles[$collname] | %{$_}
You might want to use ArrayList objects instead, as they support insertions at arbitrary locations. For example:
# C:\> $a = [System.Collections.ArrayList]#(1,2,3,4)
# C:\> $a.insert(0,6)
# C:\> $a
6
1
2
3
4
You can simply use a plus operator:
$array = #('bar', 'baz')
$array = #('foo') + $array
Note: this re-creates actually creates a new array instead of changing the existing one (but the $head, $tail = $array way of shifting you refer to works extactly in the same way).

Resources