PHP `json_encode` incorrectly turn array into `{}` - php

My system is centos 7.4 with PHP 5.4
$s='a:91:{s:13:"spotsviewvars";s:7:"1916.74";s:13:"100000T18vars";N;s:17:"100000T18S106vars";s:7:"1746.95";s:17:"100000T18S107vars";s:4:"4.49";s:17:"100000T18S108vars";s:4:"8.29";s:17:"100000T18S109vars";s:4:"4.38";s:17:"100000T18S110vars";s:3:"5.4";s:17:"100000T18S111vars";s:4:"3.88";s:17:"100000T18S112vars";s:4:"3.49";s:17:"100000T18S113vars";s:4:"5.55";s:17:"100000T18S114vars";s:4:"3.58";s:17:"100000T18S115vars";s:3:"5.5";s:17:"100000T18S116vars";s:5:"10.39";s:17:"100000T18S117vars";s:4:"6.52";s:17:"100000T18S118vars";s:4:"6.09";s:17:"100000T18S119vars";s:3:"6.7";s:17:"100000T18S120vars";s:4:"4.18";s:17:"100000T18S121vars";s:5:"14.81";s:17:"100000T18S122vars";s:3:"3.9";s:17:"100000T18S123vars";s:4:"4.93";s:17:"100000T18S124vars";s:4:"4.06";s:17:"100000T18S125vars";s:4:"5.03";s:17:"100000T18S126vars";s:4:"5.73";s:17:"100000T18S127vars";s:4:"3.13";s:17:"100000T18S128vars";s:3:"7.2";s:17:"100000T18S129vars";s:4:"7.03";s:17:"100000T18S130vars";s:4:"3.81";s:17:"100000T18S131vars";s:3:"7.4";s:17:"100000T18S132vars";s:4:"7.82";s:17:"100000T18S133vars";s:4:"3.96";s:13:"100000T19vars";N;s:17:"100000T19S134vars";N;s:17:"100000T19S135vars";N;s:17:"100000T19S136vars";N;s:17:"100000T19S137vars";s:5:"12.54";s:17:"100000T19S138vars";N;s:17:"100000T19S139vars";N;s:17:"100000T19S140vars";N;s:17:"100000T19S141vars";N;s:17:"100000T19S142vars";N;s:17:"100000T19S143vars";N;s:17:"100000T19S144vars";N;s:17:"100000T19S145vars";N;s:17:"100000T19S146vars";N;s:17:"100000T19S147vars";N;s:17:"100000T19S148vars";N;s:17:"100000T19S149vars";N;s:13:"100000T18S106";s:2:"A2";s:13:"100000T18S107";s:2:"A2";s:13:"100000T18S108";s:2:"A2";s:13:"100000T18S109";s:2:"A2";s:13:"100000T18S110";s:2:"A2";s:13:"100000T18S111";s:2:"A2";s:13:"100000T18S112";s:2:"A2";s:13:"100000T18S113";s:2:"A2";s:13:"100000T18S114";s:2:"A2";s:13:"100000T18S115";s:2:"A2";s:13:"100000T18S116";s:2:"A2";s:13:"100000T18S117";s:2:"A2";s:13:"100000T18S118";s:2:"A1";s:13:"100000T18S119";s:2:"A2";s:13:"100000T18S120";s:2:"A1";s:13:"100000T18S121";s:2:"A1";s:13:"100000T18S122";s:2:"A2";s:13:"100000T18S123";s:2:"A2";s:13:"100000T18S124";s:2:"A2";s:13:"100000T18S125";s:2:"A2";s:13:"100000T18S126";s:2:"A1";s:13:"100000T18S127";s:2:"A2";s:13:"100000T18S128";s:2:"A1";s:13:"100000T18S129";s:2:"A1";s:13:"100000T18S130";s:2:"A2";s:13:"100000T18S131";s:2:"A2";s:13:"100000T18S132";s:2:"A1";s:13:"100000T18S133";s:2:"A2";s:13:"100000T19S134";N;s:13:"100000T19S135";N;s:13:"100000T19S136";N;s:13:"100000T19S137";s:0:"";s:13:"100000T19S138";N;s:13:"100000T19S139";N;s:13:"100000T19S140";N;s:13:"100000T19S141";N;s:13:"100000T19S142";N;s:13:"100000T19S143";N;s:13:"100000T19S144";N;s:13:"100000T19S145";N;s:13:"100000T19S146";N;s:13:"100000T19S147";N;s:13:"100000T19S148";N;s:13:"100000T19S149";N;}';
$s_array=unserialize($s);
var_dump($s_array);
$s_json=json_encode($s_array,JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
var_dump($s_json);
You will notice strange result when run above PHP script.
$s_array is array,json_encode result should be something like [],but result is {}.
What's the problem?

You appear to just have been confused by differences in terminology.
In PHP an "array" can either be an indexed array (in which you have a sequence of values) or an associative array (in which you have name => value pairs).
In JSON a sequence of values is stored in an array, and a set of name => value pairs is stored in an object.
Since you have name => value pairs in your data, you get an object when converting it to JSON.
For comparison:
$indexed_array = [ "foo", "bar", "baz" ];
$associative_array = [ "foo" => "A", "bar" => "B", "baz" => "C" ];
print json_encode($indexed_array);
print "\n";
print json_encode($associative_array);

The code is working exactly as it should.
What you've got there is an associative array - i.e. each entry has a name (like "spotsviewvars", or "100000T18vars" rather than a numeric index (like 0 or 1). It's effectively a set of key/value pairs.
So in order to preserve that information when encoding as JSON, it has to be turned into an object instead - JSON has no concept of associative arrays. The only possible JSON representation which keeps both the key (e.g. "spotsviewvars") and the associated value (e.g. "1916.74") is an object.
If you turned it into a plain array you'd lose the key information, which I would assume is important. Every value would just have a numeric index to hold it instead, and you wouldn't know what its original meaning was.

Related

Are keys inherent to arrays?

It seems that all my questions are so basic that I can't find answers for them anywhere, probably because all the guides assume you have at least some basic knowledge. Anyway, on to my question...
With regard to PHP, are keys inherent to arrays? In other words, if I get data from a form that gives me a set of values in the $_POST array, are there keys assigned to the values by default, or do keys only exist if they are created explicitly? I am assuming there are no keys if I don't create them, but I suspect that there could be numerical keys assigned to each value automatically.
In the most basic sense - "key" is just an instruction for computer how to find required value in the array. So key is like an address of value cell. And you don't find a house in a city without an address - so you will likely don't find value in the array without a key either. Most programming languages supports plain arrays, where key is just an integer - 0,1,2,3,... Consider this array's element layout in memory:
Element index/key: 0 1 2 3 4
Value: A B C D E
And when you ask for a computer - give me array[3] element - it knows that
it needs to look at memory cell array_byte_offset_in_ram + size_in_bytes_of(array_element) * 3
Same instruction expressed in human language will be "find where first array element is stored in memory and jump from it forward in memory by 3x memory amount which is needed to store 1 array element". By doing this algo finds your cell and fetches your value D.
For arrays of arbitrary keys, when key can be any string - is another story. But idea remains the same - from the key computer should deduce How to find required element cell in memory. Usually this done by translating arbitrary string keys into integer hash values. Then sorting these hashes and performing binary search algorithm to find integer-index of required hash value. Last step is to pass index found into another plain array where your real values are stored.
Consider this array:
Element key: 'ABC' 'EFG' 'CDE'
Value: a b c
There are many ways to calculate hashes, but for simplicity consider stupid hash function
hash(string) = sum(ascii_values_of_chars_in_string)
So we have following hash table:
hash('ABC') = ord('A')+ord('B')+ord('C')
hash('EFG') = ord('E')+ord('F')+ord('G')
hash('CDE') = ord('C')+ord('D')+ord('E')
After sorting hashes we generate and save such hash array:
hash[0] = 198
hash[1] = 204
hash[2] = 210
Now we can save array values into another plain array where integer index should be the same as hash array index of saved hash(key) function output =>
value[0] = 'a'
value[1] = 'c'
value[2] = 'b'
Now when you request - give me array['EFG'] value - computer calculates key 'EFG' hash which is 210. Then by employing binary search algo finds 210 value in hash table and deduces that it's index in hash table is 2. So it jumps to value table at index 2 by using above described technique of plain arrays and fetches resulting value of 'b' which will be returned to you.
These are the main principles of array keys. Of course there are much more things under the hood - such as hash collisions and etc. But at this point you don't need more complexities as for now. Simply keep in mind that at most bare-bones of computer architecture - there is only plain numbers and math operating on them - no fancy things like "strings"/"objects" and another cosmos :-)
If you assign an existing array to a new variable, it will be like you copied that array to that variable.
So let's say you have:
$initialArray = ["test1" => "My First Test", "test2" => "My Second Test"];
If you initialize a new variable and say it should be equal to the array you desire:
$aNewArray = $initialArray;
Your new array will be exactly like the one you said for it to copy;
Also, if you change $initialArray after you copied to the $aNewArray, your changes will only affect the variable you change, keeping your $aNewArray with the same data before you changed.
Now, if you just set a few variables into an array without specifying keys to access them, it will automatically link them by numeric index:
$arrayWithoutSpecificKeys = ["one", "two", "three"];
print_r($arrayWithoutSpecificKeys);
This output will be:
array (
0 => "one",
1 => "two",
2 => "three"
);
Never forget array start with index 0;
This means if you assign $_POST to a variable, it will inherit the key => values transmitted.
In your form you will name you inputs like this:
<input type="text" name="surname" .../>
Your $_POST variable will have an array with whatever information you set in your input, and link them as bellow:
["surname" => "<your typed value>"]
Then again, if you copy the $_POST to a variable, that variable will inherit all the content that $_POST contains;
Hope it helped!
An array in PHP is actually an ordered map. A map is a type that
associates values to keys.
PHP Documentation
This means that you can only have one index, however you need to be aware that arrays implement an internal pointer, and technically you can iterate the array by sequentially hopping through each array entry. This is what foreach does for you. You can check next documentation for more details.
In case if you don't supply keys when creating an array, then keys will be assigned automatically. Array created by the following line of code will assign index (key) for each of its elements (starting from 0):
$array = array("foo", "bar", "hello", "world");

Can PHP arrays hold items of different type?

In other programming languages the definition of arrays is something which can hold similar kind of elements. For example if I declare something like int i[] it will store integers, but in PHP a single array seems to be holding strings and numbers together.
Will the number/integer be treated as string in such type of array in PHP?
According to the PHP manual you can indeed store heterogeneous types inside a PHP "array" - scroll down to example 3.
Note that even though the example is about keys being ints or strings, the values assigned in the example are also both ints and strings, demonstrating that it is possible to store heterogeneous types.
Be aware that in the case of different-typed keys there is automatic casting involved so you may have surprising results in the case where e.g. a string contains a valid decimal representation.
Yes. A PHP array can have multiple data types in it.
Also, you should note that arrays in PHP actually are represented in the form of key-value pairs, where the elements you will input into the array are values.
You can explicitly define keys too, when entering elements into the array, but when you don't, PHP will use indices starting from 0.
Example:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
?>
PHP will interpret as
array(4) {
["foo"]=>
string(3) "bar"
["bar"]=>
string(3) "foo"
[100]=>
int(-100)
[-100]=>
int(100)
}
Reference- http://php.net/manual/en/language.types.array.php
You can store anything you want in an array.
Will the number/integer be treated as string in such type of array in PHP?
Not upon storing it. However, when you use a value as such, PHP will convert it. The usage of a value determines its interpretation. (Attention, the key is converted upon storing, however, if it is considered numerical)
Not going to put oil on the fire of the PHP Arrays are no arrays here…
But yes, you can put different variable types (string, int, …) together in a PHP thing called Array.

JSON_ENCODE of multidimensional array giving different results

When doing a json_encode a multidimensional array in PHP, I'm noticing a different output simply by naming one of the arrays, as opposed to not naming them. For Example:
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
json_encode($arrytest)
gives a single array of multiple json objects
[{"a":1,"b":2},{"c":3},{"d":4}];
whereas simply assigning a name to the middle array
$arrytest = array(array('a'=>1, 'b'=>2),"secondarray"=>array('c'=>3),array('d'=>4));
json_encode($arrytest)
creates a single json object with multiple json objects inside
{"0":{"a":1,"b":2},"secondarray":{"c":3},"1":{"d":4}};
why would the 1st option not return the same reasults as the 2nd execpt with "1" in place of "secondarray"
In JSON, arrays [] only every have numeric keys, whereas objects {} have string properties. The inclusion of a array key in your second example forces the entire outer structure to be an object by necessity. The inner objects of both examples are made as objects because of the inclusion of string keys a,b,c,d.
If you were to use the JSON_FORCE_OBJECT option on the first example, you should get back a similar structure to the second, with the outer structure an object rather than an array. Without specifying that you want it as an object, the absence of string keys in the outer array causes PHP to assume it is to be encoded as the equivalent array structure in JSON.
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
// Force the outer structure into an object rather than array
echo json_encode($arrytest , JSON_FORCE_OBJECT);
// {"0":{"a":1,"b":2},"1":{"c":3},"2":{"d":4}}
Arrays with continuous numerical keys are encoded as JSON arrays. That's just how it is. Why? Because it makes sense.
Since the keys can be expressed implicitly through the array encoding, there is no reason to explicitly encoded them as object keys.
See all the examples in the json_encode documentation.
At the first option you only have numeric indexes (0, 1 and 2). Although they are not explicitly declared, php automatically creates them.
At the second option, you declare one of the indexes as an string and this makes PHP internally transform all indexes to string.
When you json encode the first array, it's not necessary to show the integers in the generated json string because any decoder should be able to "guess" that they are 0, 1 and 2.
But in the second array, this is necessary, as the decoder must know the key value in your array.
It's pretty simple. No indexes declared in array? Them they are 0, 1, 2, 3 and so on.
output of this as in json form is year1{a,b},year2{c}, year3{d}
**a has value 1 ,b=2,c=3,d=4 stored in array of year1's a,b years2's c and years3's d respectivily
$array1 = array('a'=>1, 'b'=>2);
$array2 = array('c'=>3);
$array3 = array('d'=>4)
$form = array("year1" =>$array1,
"year2" =>$array2,
"year3" =>$array3,
);
$data = json_encode($form);

What are Arrays in PHP

As per standard Array definition: An array is a variable which allows you to store multiple value of same Data Type.
In PHP, say $a=array("abc",123,"4");
What will be $a[0] abc , $a[1] 123 and $a[2] 4 treated as String, Numeric value or character value and Why?
Arrays in PHP are different, there's only one type of array which an store different types. in Your example the items keep their original type. abc is a String, 123 is a number and 4 is a string.
You can even have nonnumeric keys. For Example $a["a"] = "test".
In php arrays are not arrays.
If you really want to know how this whole thing works, i would recommend for you to watch this presentations: PHP UK Conference 2012 - PHP under the hood, by Johannes Schlüter.
Also, as #RepWhoringPeeHaa mentioned : use var_dump().
PHP treats array differently from general definition of them.
I suggest you read more about them on the official docs.
Arrays
An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more. As array values can be other arrays, trees and multidimensional arrays are also possible.
Specifying with array()
An array can be created using the array() language construct. It takes any number of comma-separated key => value pairs as arguments.
array(
key => value,
key2 => value2,
key3 => value3,
...
)
The comma after the last array element is optional and can be omitted. This is usually done for single-line arrays, i.e. array(1, 2) is preferred over array(1, 2, ). For multi-line arrays on the other hand the trailing comma is commonly used, as it allows easier addition of new elements at the end.
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>

Are numeric and associative arrays in PHP two different things?

This is a deeper dive into a previous question I had here: Can items in PHP associative arrays not be accessed numerically (i.e. by index)?
According to W3Schools, :
In PHP, there are three kind of
arrays:
Numeric array - An array with a numeric index
Associative array - An array where each ID key is associated with a value
Multidimensional array - An array containing one or more arrays
But is this accurate? Each element in the array can be assigned either an index or a string as a key- so what happens when the two are mixed in the same array?
$myArray[0] = 'value1';
$myArray['one'] = 'value2';
All arrays in PHP are the same; they're implemented as hash maps which associate keys to values, whatever type the keys may be.
Manual:
The indexed and associative array types are the same type in PHP, which can both contain integer and string indices.
If an array had both numeric and non-numeric indices, though, I'd still call it an associative array. The meaning of "associative" still stands.
Wikipedia:
An associative array is an abstract data type composed of a collection of unique keys and a collection of values, where each key is associated with one value (or set of values).
...
From the perspective of a computer programmer, an associative array can be viewed as a generalization of an array. While a regular array maps an integer key (index) to a value of arbitrary data type, an associative array's keys can also be arbitrarily typed. In some programming languages, such as Python, the keys of an associative array do not even need to be of the same type.
For the last sentence, the same applies for PHP, as shown in your example.
PHP doesn't really have arrays. They are dictionaries. Numeric keys are allowed at the same time as string keys. They can be mixed and do coexist.
(Actually string keys like "123" are always treated as integers. PHP does not keep the type information for them.)
If you want a different behaviour you could implement and extend ArrayObject however. And it would be possible to implement a map, where numeric keys functioned as alias to string indexes.
In general, you should read the official documentation rather than W3Schools.
An array can contain whatever members it wants with whatever keys it wants.
The description provided by W3Schools is quite ambiguous, or even wrong.
Numeric array - An array with a numeric index
I'd say a numeric array is an array with only integer indexes. An array with one I'd probably call a mixed (or associative, see below) array, if I had to call it anything.
Associative array - An array where each ID key is associated with a value.
I don't know about that description. I'd say an array can be associative if it maps strings to values instead of numerical indexes.
Multidimensional array - An array containing one or more arraysNumeric array - An array with a numeric index
An associative array can contain arrays too, which makes it multidimensional.
Keep in mind that an array with all numeric keys (even if in a string) will always be treated as a numeric array. This can mean different things in different contexts.
$arr = array(
'1' => 'abc',
2 => 'def'
);
var_dump($arr);
Output
array(2) {
[1]=>
string(3) "abc"
[2]=>
string(3) "def"
}
You get an associative array. Try this code:
$myArray[0] = 'value1';
$myArray['one'] = 'value2';
echo($myArray[1]);
See? It doesn't echo anything.
Something inportant to note about a PHP well ordered numerical array versus a un-ordered numerical PHP array where the order is not respected (3, 1, 2, 0 instead of 0, 1, 2, 3 ...) is when you are working with an API returning JSON payloads. On the client side, e.g a client written in Javascript, and if you're expecting an array and not an object you could have some difficulties. That's why sometime, on the PHP side, you can see something as follows being returned :
return array_values($array);

Categories