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

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...

Related

Invalid JSON format in using array_unique function [duplicate]

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

Convert Single Object into an Array containing that Object

I have a number of JSON files and when there is a single object in them, their datatype is inconsistent. I am trying to alter the files that contain one item so that the element I am referencing is always an array.
Here's an example of a 'good' JSON file:
{
"apiv2": {
"items": [{
"id": "00001",
"name": "ITEM 1"
}, {
"id": "00002",
"name": "ITEM 2"
}]
}
}
In PHP terms, $json->apiv2->items is always an array I can apply the same functions to.
Every so often I have a JSON file that contains one item:
{
"apiv2": {
"items": {
"id": "00003",
"name": "ITEM 3"
}
}
}
When I attempt to iterate through 'items' with the same functions, they fail as it is now an object instead of an array.
My goal is to alter the JSON data and rewrite the file so the single item files are consistent with the multiple item files:
{
"apiv2": {
"items": [{
"id": "00003",
"name": "ITEM 3"
}]
}
}
Maybe it's because it's Friday afternoon, but I can't seem to wrap my head around this one. I thought it would be as simple as:
$json->apiv2->items = (array) $json->apiv2->items;
But that just turns it into an array with two elements, "id" and "name", not one element with the object.
As I said in the comments
When you do
$json->apiv2->items = (array) $json->apiv2->items;
PHP will convert $items to an actual array [ "id" => "00003", "name" => "ITEM 3"]
Which will give you the results ['items' => [ "id" => "00003", "name" => "ITEM 3"]]
Instead of converting your object, you need to wrap it
$json->apiv2->items = [$json->apiv2->items];
More advanced: since sometimes items can be an array and sometimes not, you can make a function [1] to wrap them
function wrap($value)
{
if (is_null($value)) {
return [];
}
return is_array($value) ? $value : [$value];
}
$json->apiv2->items = wrap($json->apiv2->items);
POC : https://3v4l.org/7p9b0
[1] Stolen from Laravel helpers
Use json_decode() and access it like this:
$json = '{"apiv2":{"items": [{"id": "00001", "name": "ITEM 1" }, {"id": "00002", "name": "ITEM 2" }]}}';
print_r(json_decode($json, true)['apiv2']['items']);

PHP: Convert Object to Associative Array with Object Property as Key

In PHP, I'd like to convert an array of objects like the following to a PHP array, using one of the properties as the associative array keys.
[
{ "id": 2, "name": "Suzy" },
{ "id": 3, "name": "Joe" },
{ "id": 4, "name": "Sara" }
]
like this...
[
2 => "Suzy",
3 => "Joe",
4 => "Sara"
]
I can't use array_map because you can't set the keys from my understanding, but I'm wondering if there's a one-liner way to do it without a foreach loop.
To be clear, I want to maintain the keys in the output array, not puts the original keys inside the new array values like they do here: PHP's array_map including keys
It appears by "object" you mean a JSON object. Given that, you can use array_column() to pull out a single column from each row, and then array_combine() to use one column for the keys and another for the values:
$json = '[
{ "id": 2, "name": "Suzy" },
{ "id": 3, "name": "Joe" },
{ "id": 4, "name": "Sara" }
]';
$array = json_decode($json, true);
$out = array_combine(array_column($array, 'id'), array_column($array, 'name'));
print_r($out);
Yields:
Array
(
[2] => Suzy
[3] => Joe
[4] => Sara
)
2 liners and has a foreach though.
<?php
$json = '[
{ "id": 2, "name": "Suzy" },
{ "id": 3, "name": "Joe" },
{ "id": 4, "name": "Sara" }
]';
$new_array = [];
foreach(json_decode($json,true) as $each_object) $new_array[$each_object['id']] = $each_object['name'];
print_r($new_array);
$json = '[
{ "id": 2, "name": "Suzy" },
{ "id": 3, "name": "Joe" },
{ "id": 4, "name": "Sara" }
]';
$array = json_decode($json, true);
$result = array_column($array, 'name', 'id');

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

Add new key/value pair into JSON in PHP

I have a result from my MySQL DB that I'm json encoding in PHP, the result looks like
:
[
{
"id": "8488",
"name": "Tenby",
"area": "Area1"
},
{
"id": "8489",
"name": "Harbour",
"area": "Area1"
},
{
"id": "8490",
"name": "Mobius",
"area": "Area1"
}
]
What I would like to do is to add a new key/value pair to that JSON so that it will be :
[
{
"id": "8488",
"name": "Tenby",
"area": "Area1",
"image": "1278.jpg"
},
{
"id": "8489",
"name": "Harbour",
"area": "Area1",
"image": "1279.jpg"
},
{
"id": "8490",
"name": "Mobius",
"area": "Area1",
"image": "1280.jpg"
}
]
So how can I do that in PHP?
<?php
$data[0]['id']="8488";
$data[0]['name']="Tenby";
$data[0]['area']="Area1";
$data[1]['id']="8489";
$data[1]['name']="Harbour";
$data[1]['area']="Area1";
$data[2]['id']="8490";
$data[2]['name']="Mobius";
$data[2]['area']="Area1";
echo json_encode($data)."<br/>";
/*Add Image element (or whatever) into the array according to your needs*/
$data[0]['image']="1278.jpg";
$data[1]['image']="1279.jpg";
$data[2]['image']="1280.jpg";
echo json_encode($data);
?>
PHP is not very good with JSON. Its best to convert from JSON to Array to do this - what #egig has also recommended.
Example code:
$temp = json_decode($json);
$temp[] = new data, whatever you want to add...;
$json = json_encode($temp);
Hope this helps.
hu?
the result of the db query will be an array or an object...
add the additional entry to that data, only encode after every necessary data manipulation is done
alternatives, but clumsy (horrible):
json_decode, add stuff, json_encode
build your additional data as a string, str_replace for example "area": "Area1" in your json string with "area": "Area1", "image": "1278.jpg"
but really:
output formatting like json_encode should only be done once you are sure that you have the whole output together and it is send out
Maybe things have changed since then, but I know this will work at this current stage:-
So here is the JSON string:-
$strJSON = '[
{
"id": "8488",
"name": "Tenby",
"area": "Area1"
},
{
"id": "8489",
"name": "Harbour",
"area": "Area1"
},
{
"id": "8490",
"name": "Mobius",
"area": "Area1"
}
]';
If this is still a string, then I would convert it into an object like this:-
$json = json_decode( $strJSON );
Now that it is in object format, to add my "image" keys with their values, I would then add them like it is shown below:-
$json[0]->image = "1278.jpg";
$json[1]->image = "1279.jpg";
$json[2]->image = "1280.jpg";
So then if I add the code below after the above code:-
echo "<pre>";
print_r( $json );
echo "</pre>";
We should then see it outputting on the page like so:-
Array
(
[0] => stdClass Object
(
[id] => 8488
[name] => Tenby
[area] => Area1
[image] => 1278.jpg
)
[1] => stdClass Object
(
[id] => 8489
[name] => Harbour
[area] => Area1
[image] => 1279.jpg
)
[2] => stdClass Object
(
[id] => 8490
[name] => Mobius
[area] => Area1
[image] => 1280.jpg
)
)
//$index = some value in array;
for($i=0;$i<count($index);$i++){
$data[$i]->key = $index[$i];
}
print $data;

Categories