Ако искате автоматично да преобразувате низове в числа при json_encode тогава един от начините е с JSON_NUMERIC_CHECK.
Но при него има доста често срещани проблеми като изрязването на телефоните и големите числа.
Това се отнася най-вече за запазени в някакъв обект, база от данни, или други които са пресметнати и са представени в консистентен формат. Например: при запазване на числата +123, 0123, 123 винаги ще се запазят като 123. Когато взимаме тези данни ние знаем, че подадените ни данни ще са вече изчислени, обработени и +123 не може да срещнем ако числото наистина не е низ от символи.
Ето една реализация на същата функционалност както при JSON_NUMERIC_CHECK, която не създава такива проблеми. Числата се заменят само ако не са толкова големи и ако не започват с „+“ или „0“ (т.е. са изчислени числа).
Опростената версия на кода:
function stringToNumeric(&$element) { if(is_string($element) && is_numeric($element)) { //Check if normal int or float and change format if (ctype_digit($element) && strval(intval($element)) === $element) { $element = intval($element); } elseif(strval(doubleval($element)) === $element) { $element = doubleval($element); } } } function arrayStringsToNumeric(&$array) { array_walk_recursive($array, "stringToNumeric"); } function jsonNumericEncode($data, $options = 0, $depth = 512) { //if Has Numberic check and is_array do proper check if(($options & JSON_NUMERIC_CHECK) == JSON_NUMERIC_CHECK && is_array($data)) { //Remove numeric check $options = $options ^ JSON_NUMERIC_CHECK; //Make proper type array_walk_recursive($data, "stringToNumeric"); } json_encode($data, $options, $depth); }
jsonNumericEncode
Функцията замества използването на JSON_NUMERIC_CHECK, но може и да се ползва директно като премахнете тази проверка.
function prepareJsonData($data) { //if Has Numberic check and is_array do proper check if((is_array($data) && !empty($data)) { //Make proper type array_walk_recursive($data, "stringToNumeric"); } } $data = prepareJsonData($data); json_encode($data);
Така накрая в данните може да получите
{ "phone": "+525526262", "number: 12512521, "phone2": "0025542424252", "money": 22.23 }
вместо
{ "phone": 525526262, "number: 12512521, "phone2": 25542424252, "money": 22.23 }
Има и друго решение, което според мен не е толкова ефективно. Можете да продължите с използването на JSON_NUMERIC_CHECK, но да промените малко данните за да се запазят все пак като низ от символи:
function prepareJsonWithNumberCheck(&$data) { array_walk_recursive($data, function(&$element) { //Check if big int or number and add space $same = strval(intval($element)) == $element; if (ctype_digit($element) && !$same) { $element = "" . $element . " "; } elseif(!$same && !preg_match('/^(\+|0)[0-9]+$/', $element)) { $element = "" . $element . " "; } }); }