Я хочу декодировать строку json для объекта PHP, а затем вернуть объект обратно в строку json без потери точности для чисел float в json.
Если вы запустите образец ниже, вы увидите:
JSON: string '{ "integer1": 10000, "integer2": 100000999499498485845848584584584, "float1": 1.121212, "float2": 8.226347662837406e+09 }' (length=130) JSON WITHOUT SPACES [1]: string '{"integer1":10000,"integer2":100000999499498485845848584584584,"float1":1.121212,"float2":8.226347662837406e+09}' (length=112) OBJECT: object(MyObject)[1] public 'integer1' => int 10000 public 'integer2' => float 1.000009994995E+32 public 'float1' => float 1.121212 public 'float2' => float 8226347662.8374 JSON FROM OBJECT [2]: string '{"integer1":10000,"integer2":1.000009994995e+32,"float1":1.121212,"float2":8226347662.8374}' (length=91)
Я хочу, чтобы строки [1] и [2] были равны или, по крайней мере, не теряли точность. Я знаю, что десятичные числа не могут быть представлены точно в PHP-поплавках, и я знаю, что вы можете использовать опцию json_decode($json, true, 512, JSON_BIGINT_AS_STRING)
для представления числа как строки в PHP. Но используя эту опцию, я могу повторно создать исходный json из объекта.
<?php $json = <<<EOT { "integer1": 10000, "integer2": 100000999499498485845848584584584, "float1": 1.121212, "float2": 8.226347662837406e+09 } EOT; // json_last_error_msg (PHP 5 >= 5.5.0) if (!function_exists('json_last_error_msg')) { function json_last_error_msg() { static $errors = array( JSON_ERROR_NONE => null, JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' ); $error = json_last_error(); return array_key_exists($error, $errors) ? $errors[$error] : "Unknown error ({$error})"; } } class MyObject { /** @var int|float */ public $integer1; /** @var int|float */ public $integer2; /** @var int|float */ public $float1; /** @var int|float */ public $float2; public function __construct($json) { $this->fromJson($json); } public function fromJson($json) { $result = json_decode($json); if (json_last_error() != JSON_ERROR_NONE) { die('json_decode error: '.json_last_error_msg()); }; $this->integer1 = $result->integer1; $this->integer2 = $result->integer2; $this->float1 = $result->float1; $this->float2 = $result->float2; } public function toJson() { $json = json_encode($this); if (json_last_error() != JSON_ERROR_NONE) { die('json_decode error: '.json_last_error_msg()); }; return $json; } } echo 'JSON: '; var_dump($json); echo 'JSON WITHOUT SPACES [1]: '; var_dump(preg_replace('/\s+/', '', $json)); $object = new MyObject($json); echo 'OBJECT: '; var_dump($object); echo 'JSON FROM OBJECT [2]: '; var_dump($object->toJson());
Я полагаю, что я мог бы добавить дополнительные метаданные к объекту и указать, было ли свойство строки номером в исходной строке json, но тогда мне пришлось бы разбирать json самостоятельно и не использовать функцию json_decode.
Я прочитал много сообщений по этому вопросу, но все они сказали только, как преобразовать json в объект (используя строку), но не как преобразовать этот объект в исходный json как число в json.
Если вы хотите сыграть с образцом: http://sandbox.onlinephpfunctions.com/code/8d934874c93c4574d886dbbf645a6763ba1ba131