PHP confusing Object with Array after parsing JSON data - php

having parsed an object of nested objects and nested arrays PHP is mixing them up. it works well on some objects but not on others
$f = json_decode($jsonObject, true);
example of nested objects that php recognises as objects:
examples of arrays which php recognises as objects in arrays:
examples of object which php recognises as an arrays:
if i begin mixing arrays of objects it no longer recognises simple objects, it interprets them as arrays.
how can i get php to fully recognise arrays and objects in JSON,

You can turn php objects or arrays into json with json_encode()
They will come out as an array or an object depending on whether you set the extra flag when decoding. json_decode($jsonstr,true) will return an array, json_decode($jsonstr) will return an object.
It doesn't matter whether the data was an object or an array before it went in, it only matters how you decode it.
Your code above will always return an array regardless of whether you encode an object or an array.

Related

json_encode as per keys

For example I have php array as:
$arr = ["a"=>[],"b"=>[]];
for which I need json object as:
{"a":[],"b":{}}
I have huge array for which json_encode function is applied. If I put option as json_encode($data,JSON_FORCE_OBJECT) then it will make every [] object to {} object which is highly undesirable.
Can I apply encode option specific to array keys? Because one should be able to make {"a":[],"b":{}} from php array which is valid json.
you can use anonymous classes for this, like(DEMO):
$arr = ["a"=>[],"b"=>new class{}];
This way you can collectively turn some keys into objects and others into arrays.
You can also use the typecast (object), like(DEMO):
$arr = ["a"=>[],"b"=>(object)[]];
I would personally prefer the typecasting method.

Print value from stdClass Object/array with curly brackets

Using PHP, I printed out an array ($result) using print_r. But the format in which the array has been returned is a new one on me. Specifically, how do I retrieve the text found in the field "reviews_review" ("Wow, what a great...") when it's found in this particular format with its multiple values? Example:
stdClass Object
(
[node_reviews_nid] => 5270
[reviews_review] => a:2:{s:5:"value";s:38:"Wow, what a great place. The bestest!";s:6:"format";s:13:"filtered_html";}
Those extra values and curly brackets have got me stumped. If I wanted the node_reviews_nid I could simply use $result->node_reviews_nid" - but doing that to get reviews_review just retrieves too much ie,
a:2:{s:5:"value";s:38:"Wow, what a great place. The bestest!";s:6:"format";s:13:"filtered_html";})
The odd curly brackets you're seeing are the result of PHP's serialize function.
Basically it's intended to convert complex structures like objects, nested arrays and so on into simple strings which are easier and safer to transfer, for example over HTTP. Think of it as JSON representation, but specific to PHP (do not attempt to json_decode() a serialized value).
Also worth noting is that serialize-d string has a maximum length, beyond which it's simply truncated, so avoid using it for very large structures - you'll lose data.
The reverse of that is unserialize. So to read the review's text, you would first have to unserialize the "reviews_review" property, then reference the "value" index of the resulting array.
$review_data = unserialize($result->reviews_review);
$review_text = $review_data['value'];
print($review_text);
The data in reviews_review looks like a serialized array i.e. written using the serialize() function
So you will need to unserialize it using unserialize() before you can use it
$review = unserialize($obj->reviews_review);
print_r($review);

How can I make Symfony serialize empty associative arrays as empty JSON objects?

I need to serialize a set of PHP associative arrays to JSON using Symfony. Some of these arrays happen to be empty.
This means that all arrays containing data will be serialized to JSON objects whereas all empty arrays will be serialized to JSON empty arrays. Since I would like to avoid having to check whether something is an object or an array, I would prefer if all my arrays (empty or not) would be serialized to JSON objects, not arrays.
How can I achieve this with Symfony 2?
Symfony 2 allows you to pass a context to the serializer in which you can set serialization options. I could not find this in the official documentation but saw it while looking through the source code.
In order to serialize empty PHP arrays to empty JSON objects you need to pass a flag to json_encode (which is what the Symfony JSON encoder uses). You can pass arbitrary flags, basically all the options that json_encode accepts.
It works like this:
$serializer->serialize($myObject, "json", ["json_encode_options" => JSON_FORCE_OBJECT])
Since Symfony 4.4 there is a new option preserve_empty_objects that helps you - if you can convert the empty array into an empty object first:
$array = ['foo' => new stdClass()];
$serializer->serialize($array, "json", ["preserve_empty_objects" => true]);
// {'foo': {}}

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.

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

Categories