JSON_ENCODE of multidimensional array giving different results - php

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);

Related

Remove quotes from json_encoded ints prior to 5.3.3

When using json_encode, it annoyingly automatically coverts the int keys to strings. For example, if you have an array:
$a = array();
$a[12] = 15;
echo json_encode($a);
{"12":15} //notice the quotes around 12
After searching SO, the solution is to use
json_encode($array,JSON_NUMERIC_CHECK)
However, that is only available in php > 5.3.3. The production server I'm stuck with is using 5.3.2.
Surely there is a work around?
So the problem here is that you are basically mixing your approach to the data structure and json_encode() is trying to make a best guess as to how to interpret your array, since in JSON, there is not such concept of a non-zero based, numerically indexed array.
If for example, you had a zero-based numeric array with a continuous number sequence, json_encode() would encode this a a numerically-indexed array of the format:
[value1, value2, ...]
Since you don't have a zero-based array, your data structure is being interpreted as an object structure and given a string key (the only available key type for an object in JSON) of the format:
{"key", value}
So it seems you need to make up your mind as to what you are really trying to represent in your array. Do you only need a numerically based array, or do you need object encoding.

Add " and create own json array in php

I my php file, I need to make my own Json array.
for($i=1;$i<$arraySize+1;$i++){
$idJson[$i]=$i.":".$birdIDArray[$i-1];
}
for($i=$arraySize+1 ;$i<$arraySize*2+1; $i++){
$idJson[$i]=$i.":".$rankArray[$i-($arraySize+1)];
}
When I use
print(json_encode($idJson));
the OUTPUT : ["0:3","1:15","2:3","3:14","4:1","5:2","6:2"]
But i need the output like this ["0":"3","1":"15","2":"3","3":"14","4":"1","5":2","6":"2"]
When I going to add " mark
for($i=1;$i<$arraySize+1;$i++){
$idJson[$i]=$i.'"'.":".'"'.$birdIDArray[$i-1];
}
for($i=$arraySize+1 ;$i<$arraySize*2+1; $i++){
$idJson[$i]=$i.'"'.":".'"'.$rankArray[$i-($arraySize+1)];
}
It prints like this
["0:3","1\":\"15","2\":\"3","3\":\"14","4\":\"1","5\":\"2","6\":\"2"]
How can I avoid from printing this \ sign?
I'm assuming you want a JSON object like this:
{"0":"3", ... }
The problem here is that Javascript/JSON distinguishes between key-value pairs, which are objects, and numerically indexed lists, which are arrays, while PHP uses arrays for both these things. With json_encode it depends on whether the PHP array is a continuously numerically indexed array, in which case you get a JSON array, or anything else, in which case you get a JSON object.
What you want is to force a JSON object even for a continuously numerically indexed array. The first question here would be: why?! But if you're really sure you want that (again, why?!), there's the JSON_FORCE_OBJECT flag in PHP 5.3+:
echo json_encode(array("3", "15", "3"), JSON_FORCE_OBJECT);
// {"0":"3","1":"15","2":"3"}
But I'll say again that that's pretty pointless. If you use a regular array like ["3","15","3"], the keys to those elements are already implicitly 0, 1 and 2. There's no need to enforce them as object keys.

Accessing PHP objects using both naming with reserved characters (-,#) and indexes (0)

In PHP figured out how to use {name-with-reserved-chars} notation to access object data after JSON decode but I also have index values as well in the path (like [0]). My attempts to add the index value has returned nothing despite all my attempts to vary the pattern. Here is an example based on a big JSON object:
["ops:world-patent-data"]["exchange-documents"]["exchange-document"]
[0]["bibliographic-data"]["publication-reference"]["document-id"][0].date.$
my attempt gets nothing:
print $result->{'ops:world-patent-data'}->{'exchange-documents'}->{'exchange-document'}->
{0}->{'bibliographic-data'}->{'publication-reference'}->{'document-id'}->{0}->date;
wondering how to place the 0 and 1 indexes in the path ...
When deserializing an actual JSON list (i.e, not an object but an actual array with numerical indices; something like [1,2,3,...] or also [{...},{...},...]), PHP's parse_json function builds a corresponding PHP array with numerical indices (while on the other hands, it maps JSON objects to instances of the stdClass class -- unless you use the $assoc parameter of the parse_json function).
So, because you are accessing arrays instead of objects, your code would probably have to look like this:
print $result->{'ops:world-patent-data'}->{'exchange-documents'}->
{'exchange-document'}[0]->{'bibliographic-data'}->{'publication-reference'}->
{'document-id'}[0]->date;
It would probably easier to use the $assoc parameter, forcing json_decode to map the entire JSON object with associative arrays, allowing you to use the square bracket notation for object access also.

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);

Is json_decode in PHP guaranteed to preserve ordering of elements when returning an array?

You can pass a boolean to json_decode to return an array instead of an object
json_decode('{"foo", "bar", "baz"}', true); // array(0 => 'foo', 1 => 'bar', 2 => 'baz')
My question is this. When parsing object literals, does this guarantee that the ordering of the items will be preserved? I know JSON object properties aren't ordered, but PHP arrays are. I can't find anywhere in the PHP manual where this is addressed explicitly. It probably pays to err on the side of caution, but I would like to avoid including some kind of "index" sub-property if possible.
Wouldn't it make more sense in this case to use an array when you pass the JSON to PHP. If you don't have any object keys in the JSON (which become associative array keys in PHP), just send it as an array. That way you will be guaranteed they will be in the same order in PHP as in javascript.
json_decode('{["foo", "bar", "baz"]}');
json_decode('["foo", "bar", "baz"]'); //I think this would work
If you need associative arrays (which is why you are passing the second argument as true), you will have to come up with some way to maintain their order when passing. You will pry have to do some post-processing on the resulting array after you decode it to format it how you want it.
$json = '{[ {"key" : "val"}, {"key" : "val"} ]}';
json_decode($json, true);
Personally, I've never trusted any system to return an exact order unless that order is specifically defined. If you really need an order, then use a dictionary aka 2dimension array and assigned a place value (0,1,2,3...) to each value in the list.
If you apply this rule to everything, you'll never have to worry about the delivery/storage of that array, be it XML, JSON or a database.
Remember, just because something happens to work a certain way, doesn't mean it does so intentionally. It's akin to thinking rows in a database have an order, when in fact they don't unless you use an ORDER BY clause. It's unsafe to think ID 1 always comes before ID 2 in a SELECT.
I've used json_decode() some times, and the results order was kept intact with PHP client apps. But with Python for instance it does not preserve the order.
One way to be reassured is to test it over with multiple examples.
Lacking an explicit statement I'd say, by definition, no explicit order will be preserved.
My primary line of thought it what order, exactly, would this be preserving? The json_decode function takes a string representation of a javascript object literal as it's argument, and then returns either an object or an array. The function's input (object literal as string) has no explicit ordering, which means there's no clear order for the json_decode function to maintain.

Categories