Invalid JSON format in using array_unique function [duplicate] - php

This question already has answers here:
json_encode PHP array as JSON array not JSON object
(4 answers)
Closed 3 years ago.
I have removed the duplicate items for the following array, by writing:
$outcome['id'] = array_unique($outcome['id'], SORT_REGULAR);
but I'm getting undesirable JSON output
"id": {
"0": {
"id": 947,
"label": "ABCD"
},
"1": {
"id": 2175,
"label": "EFGH"
},
"2": {
"id": 15,
"label": "IJKL"
}
}
instead of the below , which is the desirable JSON output :
"id": [
{
"id": 947,
"label": "ABCD"
},
{
"id": 2175,
"label": "EFGH"
},
{
"id": 15,
"label": "IJKL"
}
]
While debugging on PHPStorm, the result shown was in array format, but on Postman, the result is being transformed to object!

array_unique preserves keys while removing items. This means it'll remove some array entries but keep indexes of remaining items intact, resulting in non-continuous numerical indices (gaps). An array with gaps in their numerical indices or an array with non-numerical indices counts as an associative array which in JSON becomes a JSON object. You can reset the indices by using array_values like e.g.
$outcome['id'] = array_values(array_unique($outcome['id'], SORT_REGULAR));

Related

PHP: Sorting a specefic key of an associative multidimensional array [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Sort an array of associative arrays by column value
(23 answers)
Closed 8 months ago.
i want my foreach loop test specefic $key of "age"from my associative decoded json data for example and ascending or descendig sort whole array by value of "age" can anyone help me?
[
{
"number": 1,
"name": "masoud ahmadi",
"age": 16,
"school": "Amir kabir"
},
{
"number": 2,
"name": "mohammad hosseini",
"age": 14,
"school": "Andishe"
},
{
"number": 3,
"name": "Mohammad hosseini",
"age": 14,
"school": "Allame"
},
{
"number": 4,
"name": "ali akabr",
"age": 16,
"school": "Allame"
}
]

Convert object of objects to array of objects (PHP, Laravel)

I am returning some data from DB using Eloquent and putting in in object of arrays. My response object to browser is displayed in this format:
// response()->json($response, 200);
[{
"id": 1,
"name": "car",
"make": ["bmw", "ford"]
"order": 1
},
{
"id": 2,
"name": "bike",
"make": ["aprilia"]
"order": 2
},
{
"id": 3,
"name": "boat",
"make": []
"order": 3
},
(...)
]
Before returning it though, I wanted to filter it on server side. So I only return objects which do hold value in the "make" array.
So I am running this loop:
foreach ($response as $key => $transport) {
if (count($response[$key]['make']) == 0) {
unset($response[$key]);
};
}
What php does is it converts the array to object and also adds keys to each inner object. So now my $response looks like:
// response()->json($response, 200);
{ // notice here it has changed from array to object
"0": { // notice here it has added key "0"
"id": 1,
"name": "car",
"make": ["bmw", "ford"]
"order": 1
},
"1" : { // notice here it has added key "1"
"id": 2,
"name": "bike",
"make": ["aprilia"]
"order": 2
},
(...)
}
First of all - why?
And second question - how to prevent/go back to array of objects response?
When you unset a value from an indexed array in PHP, the existing indexes remain. Using a simple example with a small range of integers to illustrate, the following code unsets all odd integers from an array:
$numbers = range(1, 5); // [1, 2, 3, 4, 5];
foreach ($numbers as $index => $number) {
if ($number % 2 !== 0) {
unset($numbers[$index]);
}
}
print_r($numbers);
Which yields:
Array
(
[1] => 2
[3] => 4
)
Note that the odd elements are removed, but the indexes of the existing elements are retained. Because of these gaps, the array isn't sequentially indexed at this point.
The consequence of this is, when you json_encode() this array, it assumes that these non-sequential indexes (let's just call them keys at this point) are to be retained, so it creates an object literal with keys instead. These keys are strings that just happen to be integers:
echo json_encode($numbers); // {"1":2,"3":4}
Using array_values($numbers) will reset your array's indexes:
$reindexed = array_values($numbers);
echo json_encode($reindexed); // [2, 4]
Note: I mentioned in a comment that you can cast to an array using (array)—this is actually not correct as it will retain the non sequential indexes.
Hope this helps!

how can I avoid json_encode adding key values to my array objects? [duplicate]

I'm not sure why this is happening, but I seem to run into this problem often. Here is my original JSON for a shopping cart:
{
"cartitems": [
{
"Product_ID": "1",
"quantity": "1",
"cartid": 1
},
{
"Product_ID": "5",
"quantity": "1",
"cartid": 4
},
{
"Product_ID": "5",
"quantity": "1",
"cartid": 6
},
{
"Product_ID": "5",
"quantity": "1",
"cartid": 7
}
]
}
This JSON data is stored to the $_SESSION variable, $_SESSION['cart_items']
This code is used to remove an item:
$cartid = $_POST['varA'];
/* Remove the item */
foreach ($_SESSION['cart_items']['cartitems'] as $key => $product) {
if ($product['cartid'] == $cartid) {
unset($_SESSION['cart_items']['cartitems'][$key]);
}
}
echo json_encode($_SESSION['cart_items']);
When the item with cartid = 7 is removed, the result is this when it is endoded:
{
"cartitems": {
"0": {
"Product_ID": "1",
"quantity": "1",
"cartid": 1
},
"1": {
"Product_ID": "5",
"quantity": "1",
"cartid": 4
},
"2": {
"Product_ID": "5",
"quantity": "1",
"cartid": 6
}
}
}
It adds keys! This only occurs when there are more than 3 items, which baffles me. Is there any way I can re-write my code so that it prevents theses keys from being created?
In PHP, there are only arrays, which are used for both associative and numerically indexed maps/lists/arrays. Javascript/JSON has two distinct concepts: numerically indexed arrays ([...]) and object maps ({ foo : ... }). For PHP's json_encode to decide which to use when encoding an array, there's some logic behind the scenes. Generally, if the array keys are contiguous and all numerical, the array is encoded to a JSON array ([...]). If there's even one key out of order or a non-numeric key, a JSON object is used instead.
Why your array manipulation in particular triggers an object, I don't know. To avoid this though, you can reset your array keys to make sure they're numerically, contiguously indexed:
$_SESSION['cart_items']['cartitems'] = array_values($_SESSION['cart_items']['cartitems']);
Try this, worked for me.
Transfer the array to a new array with auto keys:
/* Remove the item */
foreach ($_SESSION['cart_items']['cartitems'] as $key => $product) {
if ($product['cartid'] == $cartid) {
unset($_SESSION['cart_items']['cartitems'][$key]);
}
}
$var=array();
foreach($_SESSION['cart_items']['cartitems'] as $key => $product) {
$var['cart_items']['cartitems'][] = $product;
}
echo json_encode($var['cart_items']);

PHP - array_search appends keys with json_encode function parsing issue [duplicate]

This question already has answers here:
PHP Array to JSON Array using json_encode(); [duplicate]
(4 answers)
Closed 8 years ago.
Below is my JSON Result when I do not replace the order of channels as per timings:
"channels": [
{
"id": "1",
"name": "LBC دراما "
},
{
"id": "2",
"name": "KTV Arabe"
},
{
"id": "3",
"name": "KTV Plus"
}
]
Now, when I replace the array keys with values returned by array_search function, it brings the key with array response which is problem for me:
"channels": {
"0": {
"id": "2",
"name": "KTV Arabe"
},
"1": {
"id": "1",
"name": "LBC دراما "
},
"3": {
"id": "3",
"name": "KTV Plus"
}
}
code:
$newChannelsArr['channels'][array_search($channelsArr['channels'][$a]['id'], $data)] = ($channelsArr['channels'][$a]);
How can I overcome from keys getting appended in my json array?
My Code Snippet:
$data values:
Array
(
[0] => 2
[1] => 1
[3] => 3
)
$newChannelsArr = array();
if(isset($data)){
for($a = 0; $a < count($data); $a++){
$kv = array_search($channelsArr['channels'][$a]['id'], $data);
$newChannelsArr['channels'][(int)$kv] = ($channelsArr['channels'][$a]);
}
}
Solution:
Solution
ksort($newChannelsArr['channels']); // sort an array
$arr = array_map('array_values', $arr); // regenerate their keys
It will be a quick patch.
No, because JSON array does not have keys. That's why when you added it, in second response you now got object, not array you had before and what you wanted to be your array keys become properties of object. You cannot access object as array. You must now access it as object:
$foo->property...

json_encode() on a multidimensional array - with string keys

I am creating an very large multidimensional array using PHP. Each object contains Name, ID, ParentID and Children. Children is an array of more objects in the same format.
It is critical I name the IDs of each object - this helps me put each object under the correct parent. (In the code below, I use 101, 102 etc.)
However, the problem I am having is when I return the array in JSON using json_encode. Each 'Children' array is being printed as an object, not an array - as shown in the JSON code below.
As I read on another SO thread here, they "are made as objects because of the inclusion of string keys" - although they are numbers, they are still strings.
{
"101": {
"ID": "101",
"ParentID": "0",
"Name": "Root One"
"Children": {
"102": {
"ID": "102",
"ParentID": "101",
"Name": "Child One"
},
"103": {
"ID": "103",
"ParentID": "101",
"Name": "Child Two",
"Children": {
"104": {
"ID": "104",
"ParentID": "103",
"Name": "Child Child One"
}
}
},
Does anyone know how to overcome this issue?
Edit: The JSON should look like this (the square brackets are important!):
[
{
"ID": "101",
"ParentID": "0",
"Name": "Root One",
"Children": [
{
"ID": "102",
"ParentID": "101",
"Name": "Child One",
"Children": [
A JSON array has no explicit indexes, it's just an ordered list. The only JSON data structure that has named keys is an object. The literal should make this quite obvious:
["foo", "bar", "baz"]
This array has no named indices and there isn't any provision to add any.
PHP conflates both lists and key-value stores into one array data type. JSON doesn't.
This is your object:
$parent=new StdClass();
$parent->ID=101;
$parent->ParentID=0;
$parent->Name='Root One';
$child1=new StdClass();
$child1->ID=1011;
$child1->ParentID=$parent->ID;
$child1->Name='Child One';
$parent->Children[]=$child1;
$child1_1=new StdClass();
$child1_1->ID=10111;
$child1_1->ParentID=$child1->ID;
$child1_1->Name='Child One One';
$child1->Children[]=$child1_1;
This is your JSON convert function:
echo json_encode($parent,JSON_PRETTY_PRINT);
and this is your object coded into JSON format:
{
"ID": 101,
"ParentID": 0,
"Name": "Root One",
"Children": [
{
"ID": 1011,
"ParentID": 101,
"Name": "Child One",
"Children": [
{
"ID": 10111,
"ParentID": 1011,
"Name": "Child One One"
}
]
}
]
}
The answer came later because I started learning PHP later. Anyway, some day, someone might find it useful.
I have now got a working solution which is fast and works well.
Firstly, as written in SO link from the question;
In JSON, arrays only have numeric keys, whereas objects have string
properties. The inclusion of a array key forces the entire outer
structure to be an object by necessity.
In JSON; Curly braces hold objects ({}), Square brackets hold arrays ([]).
So using a string as a key will result in the json_encode function returning objects, whereas reseting the keys will ensure it creates arrays.
Therefore, just before I return my JSON encoded string, I run a function to reset all the array keys. The code I found on this SO thread (Reset array keys in multidimensional array) was particularly useful!
http://php.net/manual/en/function.json-decode.php
Set 2nd parameter of json_decode to true to atleast get assoc arrays.
Aside from that: javascript can't handle non-sequential/non-contiguous array indexes, so as soon as the id's are not sequential, json has no other option then to convert it into "string" indexes.

Categories