Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON_NUMERIC_CHECK and phone numbers

Tags:

json

php

Our PHP API outputs results using json_encode with JSON_NUMERIC_CHECK enabled, which is important for financial figures, binary values etc.. but we have recently introduced a phone number field, and it is removing zeros from the beginning of the number when it casts it as an integer.

I've tried to force "(string)" type on the value before it goes to json_encode, but it looks like the function is overriding it. eg:

$output = array(
    'is_bool' => 1,
    'total_amount' => '431.65',
    'phone_number' => (string) '0272561313'
);
echo json_encode($output,JSON_NUMERIC_CHECK);

Produces:

{"is_bool":1,"total_amount":431.65,"phone_number":272561313}

Any suggestions on how to best handle this would be much appreciated. I really don't want to have to resort to adding trailing spaces at the end of the phone number when it's output just to get it through as a string.

Thanks!

like image 401
Ryan Marshall Avatar asked Jul 02 '14 00:07

Ryan Marshall


4 Answers

You can try this:

{
  "is_bool": 1,
  "total_amount": 431.65,
  "phone_number": "xn#0272561313"
}

as example in mysql: SELECT CONCAT('xn#', phone_number) as phone_number...

If you used json_encode(), replace the string like this:

echo str_replace('xn#','',$your_encoded_json);
like image 62
Pablo Pixcasso Avatar answered Nov 10 '22 11:11

Pablo Pixcasso


pass the data to this function to get JSON encoding with + and 0 preceded data staying as a string. I am using double encoding and str_replace to get over the issue.

public static function json_encode($data){
    $numeric = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
    $nonnumeric = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    preg_match_all("/\"[0\+]+(\d+)\"/",$nonnumeric, $vars);
    foreach($vars[0] as $k => $v){
        $numeric = preg_replace("/\:\s*{$vars[1][$k]},/",": {$v},",$numeric);
    }
    return $numeric;
}
like image 34
Dawn Dharmishtan Avatar answered Nov 10 '22 10:11

Dawn Dharmishtan


Instead of typecasting it to a string do something like this:

$output = array(
    'is_bool' => 1,
    'total_amount' => '431.65',
    'phone_number' => '"0272561313"' // add quotations
);

echo '<pre>';
echo json_encode($output,JSON_NUMERIC_CHECK | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

It'l keep the trailing zero:

{
    "is_bool": 1,
    "total_amount": 431.65,
    "phone_number": "\"0272561313\""
}

Decode:

$test = json_encode($output,JSON_NUMERIC_CHECK | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
$test = json_decode($test, true);
print_r($test);

Output:

Array
(
    [is_bool] => 1
    [total_amount] => 431.65
    [phone_number] => "0272561313"
)
like image 24
user1978142 Avatar answered Nov 10 '22 12:11

user1978142


Had the same issue with phone numbers, this walks over an array (no objects!) to cast only numeric values not starting with 0 or + to an int or float.

        array_walk_recursive($json, function (&$value, $key)
        {
            if(is_string($value) && is_numeric($value))
            {
                // check if value doesn't starts with 0 or +
                if(!preg_match('/^(\+|0)/', $value))
                {
                    // cast $value to int or float
                    $value   += 0;
                }
            }
        });

        return json_encode($json);
like image 26
Sander Avatar answered Nov 10 '22 12:11

Sander