PHP encode JSON (2 dimensional array) - php

I am querying a table that return to fields(message_type & percentage).
I use PHP to encode the json data, here is how i do it
$json = array();
while ($row = odbc_fetch_array($rs)) {
$json[][] = $row;
}
echo json_encode($json);
output :
[ [ { "message_type" : "bullying",
"percentage" : "60"
} ],
[ { "message_type" : "cheating",
"percentage" : " 14"
} ],
[ { "message_type" : "Stress",
"percentage" : "16"
} ],
[ { "message_type" : "Gang",
"percentage" : "7"
} ]
]
As you can see json_encode function is adding curly braces, quotes and the object key name.
What I want is to parse the json as two dimensional array only, here is the desired output:
[
["bullying", 60],
["harrassment", 9],
["cheating", 14],
["Stress", 16],
["Gang", 7]
]
I also tried to encode it manually but I could not get the result I need.

PHP's json_encode() uses a certain amount of magic to determine whether a given vector is encoded as a JSON object or an array, but the simple rule is this: If the array has contiguous, zero-indexed, numeric keys, it will be encoded as an array. Any other vector (object or associative array) will be encoded as an object.
Because you are using odbc_fetch_array(), your result rows are returned as an associative array with the keys being the column names. To get the result you want you have 3 options:
Pass the result rows through array_values():
$json[] = array_values($row);
Manually construct the individual arrays:
$json[] = array($row['message_type'], $row['percentage']);
Or probably the best option is to use odbc_fetch_row() instead, which will return indexed arrays straight away:
while ($row = odbc_fetch_row($rs)) {
$json[] = $row;
}

Related

Manipulate JSON node to have [] parentheses

Json response from 3rd party platform which I cant control.
$json = '{
"question1": "answera",
"question2": [
"answerb",
"answerc"]
}';
Any 'question' can have multiple 'answers', however if there is only one 'answer' for that question the response comes back without the [] parentheses - this is breaking the insert into the next system (that I also dont have control over) as it is expecting the [].
Using PHP is there a way to manipulate the json string to be the following, irrelevant of the number of 'answers':
"question1": ["answera"],
You can convert string contents into an array. But you habe to iterate over all answers for this purpose.
Creating an array with an if-condition
<?php
$json = '{
"question1": "answera",
"question2": [
"answerb",
"answerc"
]
}';
// second parameter for array result
$array = json_decode($json, true);
foreach ($array as $question => $answer) {
if (is_string($answer) === true) {
$array[$question] = [ $answer ];
}
}
This one results into ...
array(2) {
'question1' =>
array(1) {
[0] =>
string(7) "answera"
}
'question2' =>
array(2) {
[0] =>
string(7) "answerb"
[1] =>
string(7) "answerc"
}
}
For any further JSON processing you can convert the PHP array back into JSON.
$json = json_encode($array);
Results into ...
string(109) "{
"question1": [
"answera"
],
"question2": [
"answerb",
"answerc"
]
}"
Casting with (array)
Another solution taken from the comments was mentioned by #RickN. Casting with (array) avoids the if condition and could possibly be faster, if that matters for your application.
foreach ($array as $question => $answer) {
$array[$question] = (array) $answer;
}

Compare multidimensional array with array of keys only

I have a multidimensional array that looks like this:
"fields" => {
"name": "John"
"lastname": "Doe"
}
"data" => {
"person": array:2 [
0 => {
"adress": "foo"
"phone": "bar"
},
1 => {
"adress": "foo1"
"phone": "bar1"
}
]
}
Now I want to check that in this multidimensional array the follow keys exist so my second array to compare looks like this:
[
'fields' => [
"name",
"lastname",
],
"data" => [
"person" => [
"adress",
"phone"
]
],
]
Now here's what I've tried to compare the keys of my second array with the first array:
$result = array_diff_key($firstArray, array_flip($secondArray));
But this gives me an
array_flip(): Can only flip STRING and INTEGER values!
So I need a way to recursively flip the array or maybe I am doing it a bit wrong
I have a multidimensional array that looks like this ...
This is not an array, whatever you've done it now is amorphous trash, not an array not an json object.
$result = array_diff_key($firstArray, array_flip($secondArray));
array_diff_key() finds differences - unique keys
array_flip() replaces keys with values in the array
So I need a way to recursively flip the array or maybe I am doing it a bit wrong
Don't flip arrays, stop searching differences if you want to find the same keys.
You need at least 2 arrays (or objects) to comparison. If you will have 2 (not nested) arrays use
array_intersect_key($array1,$array2);
For nested arrays... you have to get all the keys and then compare.

How to use PHP json_encode to format array data with []

Goal:
Use json_encode to format array data into a specified format
This is the needed format for the data after running through PHP json_encode:
NEEDED FORMAT
{
"top_level_data": [
{
"extension": {},
"sub_level_data1": 0
}
]
}
When I use this PHP:
$data = array('top_level_data' => array('extension' => array(),
'sub_level_data1' => 0
)
)
$data = json_encode($data);
I get this incorrect Output:
{
"top_level_data":{
"extension":[],
"sub_level_data1": 0
}
}
Question:
How can I modify my php to include the {} and the [] in the correct places as the Needed Format?
It's not clear how you're generating $data; if it's by the assignment you show then you can just add an extra layer of array at top_level_data, and cast the extension value to an object:
$data = array('top_level_data' => array(
array('extension' => (object)array(),
'sub_level_data1' => 0
)
)
);
If however you get the $data from another source, you can modify it like this:
$data['top_level_data']['extension'] = (object)$data['top_level_data']['extension'];
$data['top_level_data'] = array($data['top_level_data']);
Both methods yield this JSON:
{
"top_level_data": [
{
"extension": {},
"sub_level_data1": 0
}
]
}
Demo on 3v4l.org
json_encode will encode sequence array with []. The sequence array should has index from 0 to n. For other array, associative array and object will encoded with {}. Use the JSON_FORCE_OBJECT parameter of json_encode all the array will be encoded with {}.
Example:
echo json_encode(range(1,3)); // [1,2,3]
echo json_encode(array(2=>2)); // {"2":2}
echo json_encode(range(1,3),JSON_FORCE_OBJECT); // {"0":1,"1":2,"2":3}
echo json_encode((object)range(1,3)); // {"0":1,"1":2,"2":3}

PHP - Find an object by key in an array of objects, update its value

I have an array of objects, and want to update an attribute of one of the objects.
$objs = [
['value' => 2, 'key' => 'a'],
['value' => 3, 'key' => 'b'] ,
];
Let's say I want to set the 'value' of the object with 'key'=>'a' to 5.
Aside from iterating over the array searching for the key, is there any quicker/efficient way of doing this?
Thanks.
EDIT: There is debate as to why I can't use an associative array. It is because this array is obtained from a JSON value.
If my JSON object is this:
"obj": {
"a": {
"key": "a",
"value": 2
},
"b": {
"key": "b",
"value": 3
}
}
There is no guarantee that the order of the objects will be retained, which is required.
Hence I need an index in each object to be able to sort it using usort(). So my JSON needs to be:
"obj": {
"a": {
"key": "a",
"value": 2,
"index": 1
},
"b": {
"key": "b",
"value": 3,
"index": 2
}
}
But I cannot use usort() on an object, only on arrays. So my JSON needs to be
"obj": [
{
"key": "a",
"value": 2,
"index": 1
}, {
"key": "b",
"value": 3,
"index":2
}
]
Which brings us to the original question.
By using array_column(), you can pull all the values with the index key in the arrays. Then you can find the first occurrence of the value a by using array_search(). This will only return the first index where it finds a value. Then you can simply replace that value, as you now have the index of that value.
$keys = array_column($objs, 'key');
$index = array_search('a', $keys);
if ($index !== false) {
$objs[$index]['value'] = 5;
}
See this live demo.
http://php.net/array_search
http://php.net/array_column
You can make the array associative with array column. That way you can directly assign the value.
$objs = [ ['value'=>2, 'key'=>'a'], ['value'=>3, 'key'=>'b'] ];
$objs = array_column($objs, null, "key");
$objs['a']['value'] = 5;
https://3v4l.org/7tJl0
I want to recommend you reorginize your array lake that:
$objs = [
'a' => ['value'=>2, 'key'=>'a'],
'b' => ['value'=>3, 'key'=>'b']
];
And now
if( array_key_exists( 'a', $objs )) {
$objs ['a'] ['value'] = 5;
}
I had it like that initially. But I need for the objects to have an
index value in them, so I can run usort() on the main array. This is
because the array comes from JSON where the original order isn't
respected
Then create an index array:
// When fill `$objs` array
$objs = [];
$arrIndex = [];
$idx = 0;
foreach( $json as $item ) {
$arrIndex [ $item ['key']] = $idx;
$objs [$idx ++] = $item;
}
// And your task:
if( array_key_exists( 'a', $arrIndex )) {
$objs [ $arrIndex ['a']] ['value'] = 5;
}
Aside from iterating over the array searching for the key, is there
any quicker/efficient way of doing this?
You have to pay the price of iteration either way.
You can search your collection for the interesting object (takes linear time), or you form some kind of dictionary data structure, e.g. hash table (takes linear time) and then find the interesting object in constant time.
No free lunches here.

Prevent json_encode() from automatically generating integer keys

I'm trying to encode a two-dimensional PHP array to JSON with json_encode() and I'm having a problem:
My array looks like this:
$array = array( array( 1325368800, 6898 ) );
When I encode it to JSON using json_encode(), the output looks like this:
'data' : [
'0' : [ '0' : '1325368800', '1' : '6898' ]
]
I would like to get rid of the automatically generated integer keys and have it like this:
'data': [ [ '1325368800', '6898' ] ]
Any tips?
This can only happen if you give the JSON_FORCE_OBJECT flag to json_encode (live demo):
echo json_encode(array(array( 123, 123 )));
// outputs [[123,123]]
echo json_encode(array(array( 123, 123 )), JSON_FORCE_OBJECT);
// outputs {"0":{"0":123,"1":123}}
Make sure the second argument of json_encode is not set, or set to a value generated by ORing JSON_* constants together.
If, however, the data is an associative array, you can use array_values to get a JSON array instead of a JSON object:
$assocData = array('0' => array('0' => 123, '1'=>123));
$arrayData = array_map('array_values', array_values($assocData));
echo json_encode($arrayData);
By the way, the JSON output you cited is invalid, since it uses square brackets ([]) for objects, and misses a quote after "0.

Categories