Correct encoding for JSON numbers in PHP - php

Let's say I have such JSON:
{
id: 1,
somevalue: "text"
}
and I want to create this JSON by PHP function json_encode. I can pretty easy get this JSON in form:
{
"id": "1",
"somevalue": "text"
}
or, using JSON_NUMERIC_CHECK, in form where "id" will be numeric, but "somevalue" can be either numeric or text, depend on its content.
How can I make JSON where "somevalue" always be in text format (with quotes). I'll parse it by other language, where it is important.

Make sure values you want to be non string (like int or boolean) are entered as such into your source array:
<?php
$a = array('id' => 1, 'really' => true, 'somevalue' => 'text');
var_dump( json_decode( json_encode( $a ) ) );
gives expected:
object(stdClass)#1 (2) {
["id"]=>
int(1)
["really"]=>
bool(true)
["somevalue"]=>
string(4) "text"
}
EDIT
If you want it always to be strings, then put strings in your array in first place:
<?php
$a = array('id' => '1', 'really' => 'true', 'somevalue' => 'text');
var_dump( json_decode( json_encode( $a ) ) );
would give
object(stdClass)#1 (3) {
["id"]=>
string(1) "1"
["really"]=>
string(4) "true"
["somevalue"]=>
string(4) "text"
}
but that kills the whole purpose of having different variable types.
Of you can convert your array prior json encoding:
<?php
$a = array('id' => 1, 'really' => true, 'somevalue' => 'text');
$tmp = array();
foreach( $a as $key=>$val ) {
$tmp[$key] = (string)$val;
}
var_dump( json_decode( json_encode( $tmp ) ) );
would give in the end:
object(stdClass)#1 (3) {
["id"]=>
string(1) "1"
["really"]=>
string(1) "1"
["somevalue"]=>
string(4) "text"
}

To make somevalue always in "text" format:
$somevalue1 = 1;
$somevalue2 = "text";
$json1 = array("id" => 1, "somevalue" => (string) $somevalue1);
$json2 = array("id" => 1, "somevalue" => (string) $somevalue2);
echo json_encode($json1); // outputs {"id":1,"somevalue":"1"}
echo json_encode($json2); // outputs {"id":1,"somevalue":"text"}

On PHP> 5.3.3., you can use json_decode($array, JSON_NUMERIC_CHECK);
If you do not have PHP 5.3.3 or more I wrote this recursive function:
function json_encode_with_numbers($array) {
if(is_array($array)) {
if(count($array)>0 && array_keys($array) !== range(0, count($array) - 1)) {
echo '{';
$isFirst = true;
foreach($array as $key=>$item) {
if(!$isFirst) {
echo ",";
}
echo '"'.$key.'":';
json_encode_with_numbers($item);
$isFirst = false;
}
echo '}';
} else {
echo '[';
$isFirst = true;
foreach($array as $item) {
if(!$isFirst) {
echo ",";
}
json_encode_with_numbers($item);
$isFirst = false;
}
echo ']';
}
} else {
if(is_numeric($array)) {
echo $array;
} elseif ($array == null) {
echo "null";
} else {
echo '"'.str_replace(array('"', '\\'), array('\"', '\\\\'), $array).'"'; // escape special chars
}
}
}

Related

Generate multidimensional array based on given array

I have an array say,
$arr = ["x", "y", "z"];
What I want to achieve is create another array based on given array such as
$arr1["x" =>["y" => ["z"]]] = "some value";
Any idea to achieve this? Thanks in advance.
Edited:
'some value' is just a dummy data. What I'm trying to achieve is the multidimensional structure.
You can recursively build an array, taking and removing the first element of an array on each call :
function buildArray($arr, $someValue)
{
if (count($arr) == 0)
return $someValue;
// the key is the first element of the array,
// removed and returned at the same time using array_shift()
return [ array_shift($arr) => buildArray($arr, $someValue) ];
}
$arr = ["x", "y", "z"];
$arr1 = buildArray($arr, "some value");
var_dump($arr1);
echo "------------------------" . PHP_EOL;
// note that $arr is preserved
var_dump($arr);
This outputs :
array(1) {
["x"]=>
array(1) {
["y"]=>
array(1) {
["z"]=>
string(10) "some value"
}
}
}
------------------------
array(3) {
[0]=>
string(1) "x"
[1]=>
string(1) "y"
[2]=>
string(1) "z"
}
$keys = array('key1', 'key2', 'key3');
$value = 'some value';
$md = array();
$md[$keys[count($keys)-1]] = $value;
for($i=count($keys)-2; $i>-1; $i--)
{
$md[$keys[$i]] = $md;
unset($md[$keys[$i+1]]);
}
print_r($md);
You need to create recursive function:
function rec_arr($ar, $val){
$res = [];
if(is_array($ar) && count($ar)>0){
$tmp = $ar[0]; // catching the first value
unset($ar[0]); // unset first value from given array
sort($ar); // makes indexes as 0,1,...
$res[$tmp] = rec_arr($ar, $val); // recursion
} else {
return $val; // passing value to the last element
}
return $res;
}
Demo
Outputs:
Array
(
[x] => Array
(
[y] => Array
(
[z] => some value
)
)
)

Generate arrays from INI string

$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"';
I want to generate from that $variable an array that looks like this
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "peter"
["lastname"]=>
string(7) "griffin"
}
[1]=>
array(2) {
["name"]=>
string(5) "homer"
["lastname"]=>
string(7) "simpson"
}
}
so far this is what I have so far.
$temp = explode('\r\n', $persons);
$sets = [];
foreach ($temp as $value)
{
$array = explode('=', $value);
if ($array[0] != '')
{
$array[1] = trim($array[1], '"');
$sets[$array[0]] = $array[1];
$output = $sets;
}
}
that generates "persons.1.name" as a key and "peter" as a value
I´m not sure how to generate arrays based on "." thank you.
I tried with parse_ini_string() but basically is doing the same thing.
You can use array_reduce and explode
$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"';
$temp = explode(PHP_EOL, $variable);
$result = array_reduce($temp, function($c, $v){
$v = explode( "=", $v );
if ( trim( $v[0] ) !== "" ) {
$k = explode( ".", $v[0] );
$c[ $k[ 1 ] ][ $k[ 2 ] ] = $v[1];
}
return $c;
}, array());
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[0] => Array
(
[name ] => "peter"
[lastname ] => "griffin"
)
[1] => Array
(
[name ] => "homer"
[lastname ] => "simpsons"
)
)
Doc: http://php.net/manual/en/function.array-reduce.php
UPDATE: If you want to set depth, you can
$variable = '
persons.0.name = "peter"
persons.0.lastname = "griffin"
persons.1.name = "homer"
persons.1.lastname = "simpsons"
data = "foo"
url = so.com?var=true
';
$temp = explode(PHP_EOL, $variable);
$result = array_reduce($temp, function($c, $v){
$v = explode( "=", $v, 2 );
if ( trim( $v[0] ) !== "" ) {
$k = explode( ".", $v[0] );
$data = $v[1];
foreach (array_reverse($k) as $key) {
$data = array( trim( $key ) => $data);
}
$c = array_replace_recursive( $c, $data );
}
return $c;
}, array());
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[persons] => Array
(
[0] => Array
(
[name] => "peter"
[lastname] => "griffin"
)
[1] => Array
(
[name] => "homer"
[lastname] => "simpsons"
)
)
[data] => "foo"
[url] => so.com?var=true
)
PHP's ini parsing is limited and wouldn't parse that even if it was persons[0][name] = "peter".
Taken from my answer here How to write getter/setter to access multi-level array by key names?, first just explode on = to get the key path and value, and then explode on . for the keys and build the array:
$lines = explode("\n", $variable); //get lines
list($path, $value) = explode('=', $lines); //get . delimited path to build keys and value
$path = explode('.', $path); //explode path to get individual key names
$array = array();
$temp = &$array;
foreach($path as $key) {
$temp =& $temp[trim($key)];
}
$temp = trim($value, '"');
Also trims spaces and ".
Because each line contains the full address to and data for the array, we can create everything with a loop instead of recursion.
// Create variable for final result
$output=[];
// Loop over input lines, and let PHP figure out the key/val
foreach (parse_ini_string($variable) AS $key=>$val) {
$stack = explode('.', $key);
$pos = &$output;
// Loop through elements of key, create when necessary
foreach ($stack AS $elem) {
if (!isset($pos[$elem]))
$pos[$elem] = [];
$pos = &$pos[$elem];
}
// Whole key stack created, drop in value
$pos = $val;
}
// The final output
var_dump($output);
Output:
array(1) {
["persons"]=>
array(2) {
[0]=>
array(2) {
["name"]=>
string(5) "peter"
["lastname"]=>
string(7) "griffin"
}
[1]=>
array(2) {
["name"]=>
string(5) "homer"
["lastname"]=>
&string(8) "simpsons"
}
}
}

Assign array to another array values

Lets say i have this array:
$first = ['hi', 'by', 'nice']
I am going to assign another array to this array items.In fact doing a foreach loop and due to situation assign a new array to desired array item.
Now i want turn it to this:
$second = ['hi', 'by' => ['really' => 'yes'], 'nice']
How can i do it programmatically?
Try this
$first = ['hi', 'by', 'nice'];
foreach( $first as $key => $value )
{
$second[] = $value;
if( $value == 'by' )
{
$second[ $value ][] = array( 'really' => 'yes' );
}
}
var_dump( $second );
Output:
array(4) {
[0]=>
string(2) "hi"
[1]=>
string(2) "by"
["by"]=>
array(1) {
[0]=>
array(1) {
["really"]=>
string(3) "yes"
}
}
[2]=>
string(4) "nice"
}
This is very important, if index by is known than you can use this index for checking and store values into a new array otherwise this will failed.
Here is basic example:
<?php
$first = ['hi', 'by', 'nice'];
$newArr = array();
foreach ($first as $key => $value) {
if($value == 'by'){
$newArr[$value] = array('really'=>'yes');
}
else{
$newArr[] = $value;
}
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[0] => hi
[by] => Array
(
[really] => yes
)
[1] => nice
)
If I understand your requirement, actually there are many way exists to do this. This is mine,
<?php
$first = ['hi', 'by', 'nice'];
foreach($first as $k=>$v){
if($v !='by'){
$second[] = $v;
}else{
$second[$v] = ['really'=>'yes'];
}
}
print_r($second);
?>
Try this :
$second = $first;
$tofind = 'by';
$key = array_search($tofind, $second);
unset($second[$key]);
$second[$tofind] = array( 'really' => 'yes' );

Output multidimensional array to list

Can anyone help output a multidimensional array, please.
Not to sure where I have gone wrong.
The sort ordering looks correct, but its not displaying the results.
<?php
$atest = Array ( "0" => Array ( "id" => "913", "testname" => "qwerty1", "i" => "1" ),
"1" => Array ( "id" => "913", "testname" => "test22", "i" => "2" ),
"2" => Array ( "id" => "913", "testname" => "American1", "i" => "3" ),
"3" => Array ( "id" => "913", "testname" => "Eagle4", "i" => "4" ) );
$range = range('A','Z');
$output = array();
$output['#'] = array();
foreach($range as $letter){
$output[$letter] = array();
}
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $uc;
} else {
$output[$uc[0]][] = $uc;
}
}
}
foreach($output AS $letter => $result){
echo $letter . "<br/>--------<br/>\n";
sort($result);
foreach($result AS $indresult){
echo '' . $indresult['testname'] . '<br/>';
}
echo "<br/>\n";
}
?>
You're not putting the whole sub-array into $output, you're only putting $uc. Change the middle foreach loop to:
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $test;
} else {
$output[$uc[0]][] = $test;
}
}
}
Try to use print_r function, for example for array dump:
print_r($atest);
Try this
$output[$uc[0]][] = $test;
instead of
$output[$uc[0]][] = $uc; // only the name is stored.
See demo here

php array to javascript object

I have some case like this:
I have json data:
[{
"1377412272": {
"user_id": "1374050643",
"date": "2013-08-24",
"ip": "::1"
}
},
{
"1377412279": {
"user_id": "1374050643",
"date": "2013-08-25",
"ip": "::1"
}
}
, {
"1377412287": {
"user_id": "1377346094",
"date": "2013-08-25",
"ip": "::1"
}
}, {
"1377413058": {
"user_id": "1374050643",
"date": "2013-08-25",
"ip": "::1"
}
},
{
"1377413069": {
"user_id": "1377346094",
"date": "2013-08-25",
"ip": "::1"
}
}
, {
"1377413074": {
"user_id": "1377346094",
"date": "2013-08-25",
"ip": "::1"
}
},
{
"1377413079": {
"user_id": "1377346094",
"date": "2013-08-25",
"ip": "::1"
}
}
]
An then, I have convert to array PHP
$newArr = array();
foreach ($view['con'] as $key => $value) {
foreach ($value as $k => $v) {
if (isset($newArr[$v['user_id']][$v['date']])) {
$newArr[$v['user_id']][$v['date']]++;
}
else
$newArr[$v['user_id']][$v['date']] = 1;
$newArr[$v['user_id']][$v['date']] = isset($newArr[$v['user_id']][$v['date']]) ? $newArr[$v['user_id']][$v['date']]++ : 1;
}
}
Script above have result in json_encode with structure like this:
Array
(
[A] => Array
(
[2013-08-24] => 1
[2013-08-25] => 2
)
[B] => Array
(
[2013-08-25] => 4
)
)
and finally, I want it to be javascript object
[
["date","A","B"],
[2013-08-24,1,0],
[2013-08-25,2,4]
]
How to make it?...
To get output like this yo should do
$countArr = array();
foreach ($data as $key => $value)
{
foreach ($value as $k => $v)
{
if (isset($countArr[$v['date']][$v['user_id']]))
{
$countArr[$v['date']][$v['user_id']]++;
}
else
{
$countArr[$v['date']][$v['user_id']] = 1;
}
}
}
$newArr = array();
foreach ($countArr as $date => $val)
{
$row = array($date);
$newArr[] = array_merge(array($date), array_values($val));
}
echo "<pre>";
print_r($newArr);
echo json_encode($newArr)
If you print out $newArr it will look like this
Array
(
[0] => Array
(
[0] => 2013-08-24
[1] => 1
)
[1] => Array
(
[0] => 2013-08-25
[1] => 2
[2] => 4
)
)
json_encode will output
[["2013-08-24",1],["2013-08-25",2,4]]
I'm afraid you need to code everything manually.
One (not too simple) solution is this:
<?php
$ori_list = array(
'A'=> array(
'2013-08-24' => 1,
'2013-08-25' => 2,
),
'B'=> array(
'2013-08-24' => 3,
),
);
$modif_list = array();
// prepare the header
$header = array('date');
foreach($ori_list as $key=>$val){
if(!array_key_exists($key, $header)){
$header[] = $key;
}
}
$modif_list[] = $header;
// prepare the date_list
$date_list = array();
foreach($ori_list as $key=>$val){
foreach($val as $date=>$num){
// add the initial row for every date
$registered = false;
foreach($date_list as $date_row){
if($date_row[0] == $date){
$registered = true;
break;
}
}
if(!$registered){
$date_row = array($date);
for($i=0; $i<count($header)-1; $i++){
$date_row[] = 0;
}
$date_list[] = $date_row;
}
// put the right value to the right row
$first_index = 0;
$second_index = 0;
for($i=1; $i<count($header); $i++){
if($header[$i] == $key){
$second_index = $i;
break;
}
}
for($i=0; $i<count($date_list); $i++){
if($date == $date_list[$i][0]){
$first_index = $i;
break;
}
}
$date_list[$first_index][$second_index] = $num;
}
}
$modif_list[] = $date_list;
echo 'The PHP';
echo '<pre>';
var_dump($modif_list);
echo '</pre>';
echo 'The JSON';
echo '<pre>';
echo json_encode($modif_list);
echo '</pre>';
?>
The code will produce something like this (which I hope is what you want):
The PHP
array(2) {
[0]=>
array(3) {
[0]=>
string(4) "date"
[1]=>
string(1) "A"
[2]=>
string(1) "B"
}
[1]=>
array(2) {
[0]=>
array(3) {
[0]=>
string(10) "2013-08-24"
[1]=>
int(1)
[2]=>
int(3)
}
[1]=>
array(3) {
[0]=>
string(10) "2013-08-25"
[1]=>
int(2)
[2]=>
int(0)
}
}
}
The JSON
[["date","A","B"],[["2013-08-24",1,3],["2013-08-25",2,0]]]
PHP
$arr = array("id"=>"1");
json_encode($arr);
Javascript + PHP
var json = jQuery.parseJSON(<?=$arr?>);
var id = json.id;
I think this is what you want
$newArray = array
(
"A" => array
(
"2013-08-24" => 1,
"2013-08-25" => 2
),
"B" => array
(
"2013-08-25" => 4
)
);
$uids=array();
$da = array();
foreach($na as $uid => $value)
{
$uids[] = $uid;
foreach($value as $date => $count)
{
$da[$date][$uid]=$count;
}
}
$ra = array(array("date"));
foreach($uids as $uid)
{
$ra[0][] = $uid;
}
$i = 1;
foreach($da as $date => $value)
{
$ra[$i][] = $date;
foreach($uids as $uid)
{
if(array_key_exists($uid,$value))
{
$ra[$i][] = $value[$uid];
}
else
{
$ra[$i][] = 0;
}
}
$i++;
}
print(json_encode($ra));
Output:
[["date","A","B"],["2013-08-24",1,0],["2013-08-25",2,4]]
In php, lets call it array.php:
// Your final statment of your array.php script must be an echo statment to send the array to jQuery
$ar = array('item1' => 'value1');
$ret_val['a'] = $ar;
echo json_encode($ret_val);
In jQuery (for example, in the callback of $.post, but you can use $.ajax as well)
$.post("/path/to/array.php,
null, // not passing any values to array.php
function(data) {
console.log (data.a.item1); // writes 'value1' to the console
// (note that the 'a' in data.a.item1 in jQuery is the same as the 'a' in $ret_val in PHP)
},
"json");
}
Then you deal with the return value anyway you like, including creating the final object you seek.

Categories