Наша группа в телеграмм для обмена идеями, проектами, мыслями, людьми в сфере ИТ г.Ростова-на-Дону: @it_rostov

json_encode

json_encode - Конвертация данных в формат JSON

Описание

string json_encode ( mixed value )

Returns a string containing the JSON representation of value.

JSON (англ. JavaScript Object Notation) - текстовый формат обмена данными, основанный на JavaScript и обычно используемый именно с этим языком. Как и многие другие текстовые форматы, JSON легко читается людьми.

Список параметров

value

The value being encoded. Can be any type except a resource.

Возвращаемые значения

Возвращает данные в формате JSON string on success.

Примеры

Пример 1. A json_encode() example
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);

echo json_encode($arr);

Результат выполнения данного примера:

{"a":1,"b":2,"c":3,"d":4,"e":5}
Пример 2. A json_encode()
$json_data = array ('id'=>1,'name'=>"ivan",'country'=>'Russia',"office"=>array("yandex"," management"));
echo json_encode($json_data);
{"id":1,"name":"ivan","country":"Russia","office":["yandex"," management"]}

Пример 3. Эмулятор json_encode()
if (!function_exists('json_encode')) {
   function json_encode_($a=false) {
   if (is_null($a)) return 'null';
   if ($a === false) return 'false';
   if ($a === true) return 'true';
   if (is_scalar($a)) {
      if (is_float($a)) {
         // Always use "." for floats.
         return floatval(str_replace(",", ".", strval($a)));
      }

      if (is_string($a)) {
         static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
         return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';
      }else
         return $a;
      }

   $isList = true;
   for ($i = 0, reset($a); $i $v) $result[] = json_encode_($k).':'.json_encode_($v);
   return '{' . join(',', $result) . '}';
   }
}
}

Пример 3. Сохранение русских букв(кирилицы) при использовании json_encode()

А вот пример кодирования сервером строки JSON при помощи стандартной функции в php "json_encode()" и добавочной к ней. В результате русские буковки остаются русскими. Начиная с версии PHP 5.4.0. можно воспользоваться стандартныой опцией JSON_UNESCAPED_UNICODE

Исходный объект в кодировке UTF-8.

function json_encode_cyr($str) {
$arr_replace_utf = array('\u0410', '\u0430','\u0411','\u0431','\u0412','\u0432',
'\u0413','\u0433','\u0414','\u0434','\u0415','\u0435','\u0401','\u0451','\u0416',
'\u0436','\u0417','\u0437','\u0418','\u0438','\u0419','\u0439','\u041a','\u043a',
'\u041b','\u043b','\u041c','\u043c','\u041d','\u043d','\u041e','\u043e','\u041f',
'\u043f','\u0420','\u0440','\u0421','\u0441','\u0422','\u0442','\u0423','\u0443',
'\u0424','\u0444','\u0425','\u0445','\u0426','\u0446','\u0427','\u0447','\u0428',
'\u0448','\u0429','\u0449','\u042a','\u044a','\u042b','\u044b','\u042c','\u044c',
'\u042d','\u044d','\u042e','\u044e','\u042f','\u044f');
$arr_replace_cyr = array('А', 'а', 'Б', 'б', 'В', 'в', 'Г', 'г', 'Д', 'д', 'Е', 'е',
'Ё', 'ё', 'Ж','ж','З','з','И','и','Й','й','К','к','Л','л','М','м','Н','н','О','о',
'П','п','Р','р','С','с','Т','т','У','у','Ф','ф','Х','х','Ц','ц','Ч','ч','Ш','ш',
'Щ','щ','Ъ','ъ','Ы','ы','Ь','ь','Э','э','Ю','ю','Я','я');
$str1 = json_encode($str);
$str2 = str_replace($arr_replace_utf,$arr_replace_cyr,$str1);
return $str2;
}

Проблемы с которыми сталкиваются программисты

Доступ к полям

Проблема заключается в том что json_encode имеет доступ только к публичным полям объекта. Например если у вас есть класс

class Example {
   public $publicProperty;
   protected $protectedProperty;
   private $privateProperty;

   public function __construct($public, $protected, $private)
   {
      $this->publicProperty = $public;
      $this->protectedProperty = $protected;
      $this->privateProperty = $private;
   }
}

то результатом выполнения следующего кода будет:

$obj = new Example("some", "value", "here");
echo json_encode($obj);

// {"publicProperty":"some"}

как видно в результирующий json были включены только публичные поля.
Что же делать если нужны все поля?

Решение

Для php >= 5.4 достаточно будет реализовать интерфейс JsonSerializable для нашего класса, что подразумевает добавление метода jsonSerialize который будет возвращать структуру представляющую объект для json_encode

class Example implements JsonSerializable
{
   public $publicProperty;
   protected $protectedProperty;
   private $privateProperty;

   public function __construct($public, $protected, $private)
   {
      $this->publicProperty = $public;
      $this->protectedProperty = $protected;
      $this->privateProperty = $private;
   }

   public function jsonSerialize()
   {
      return [
      'publicProperty' => $this->publicProperty,
      'protectedProperty' => $this->protectedProperty,
      'privateProperty' => $this->privateProperty,
      ];
   }
}

Теперь мы можем использовать json_encode как и раньше

$obj = new Example("some", "value", "here");
echo json_encode($obj);

// {"publicProperty":"some","protectedProperty":"value","privateProperty":"here"}

Почему не стоит использовать подход с toJson методом?
Многие наверно заметили что подход с созданием метода возвращающего json может быть использован и в версиях php >= 5.4. Так почему же не воспользоваться им? Все дело в том что ваш класс может быть использован как часть иной структуры данных

echo json_encode([
'status' => true,
'message' => 'some message',
'data' => new Example("some", "value", "here"),
]);

и результат уже будет совсем другой. Также класс может использоваться другими программистами, для которых такой тип получение json-а с объекта может быть не совсем очевиден.

Что если у меня очень много полей в класcе?
В таком случае можно воспользоваться функцией get_object_vars

class Example implements JsonSerializable
{
   public $publicProperty;
   protected $protectedProperty;
   private $privateProperty;
   protected $someProp1;
   ...
   protected $someProp100500;

   public function __construct($public, $protected, $private)
   {
      $this->publicProperty = $public;
      $this->protectedProperty = $protected;
      $this->privateProperty = $private;
   }

   public function jsonSerialize()
   {
      $fields = get_object_vars($this);
      // что-то делаем ...
      return $fields;
   }
}

А если нужно private-поля, из класса, который нет возможности редактировать?
Может получиться ситуация когда нужно получить private поля (именно private, т.к. доступ к protected полям можно получить через наследование) в json-е. В таком случае необходимо будет воспользоваться рефлексией:

class Example
{
   public $publicProperty = "someValue";
   protected $protectedProperty;
   private $privateProperty1;
   private $privateProperty2;
   private $privateProperty3;

   public function __construct($privateProperty1, $privateProperty2, $privateProperty3, $protectedProperty)
   {
      $this->protectedProperty = $protectedProperty;
      $this->privateProperty1 = $privateProperty1;
      $this->privateProperty2 = $privateProperty2;
      $this->privateProperty3 = $privateProperty3;
   }
}

$obj = new Example("value1", 12, "21E021", false);
$reflection = new ReflectionClass($obj);

$public = [];

foreach ($reflection->getProperties() as $property) {
   $property->setAccessible(true);
   $public[$property->getName()] = $property->getValue($obj);
}

echo json_encode($public);

//{"publicProperty":"someValue","protectedProperty":false,"privateProperty1":"value1","privateProperty2":12,"privateProperty3":"21E021"}
Кодировка текстовых значений

Кириллица и другие знаки в UTF8
Второй тип распространённых проблем с json_encode это проблемы с кодировкой. Часто текстовые значения которые нужно кодировать в json имеют в себе символы в UTF8 (в том числе кириллица) в результате эти символы будут представлены в виде кодов:

echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $");

// "\u043a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430 or \u20b3 \u0192 \u5143 \ufdfc \u20a8 \u0bf9 \uffe5 \u20b4 \uffe1 \u0e3f \uff04"

Отображение таких символов лечится очень просто — добавлением флага JSON_UNESCAPED_UNICODE вторым аргументом к функции json_encode:

echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $", JSON_UNESCAPED_UNICODE);
// "кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $"

Символы в других кодировках
Функция json_encode воспринимает строковые значения как строки в UTF8, что может вызвать ошибку, если кодировка другая. Рассмотрим маленький кусочек кода (данный пример кода максимально упрощен для демонстрации проблемной ситуации)

echo json_encode(["p" => $_GET['p']]);

На первый взгляд ничего не предвещает проблем, да и что здесь может пойти не так? Я тоже так думал. В подавляющем большинстве случаев все будет работать, и по этой причине поиск проблемы занял у меня несколько больше времени, когда я впервые столкнулся с тем что результатом json_encode было false.

Для воссоздания такой ситуации предположим что p=%EF%F2%E8%F6%E0 (на пример: localhost?=%EF%F2%E8%F6%E0 ). *Переменные в суперглобальных массивах $_GET и $_REQUEST уже декодированы.

$decoded = urldecode("%EF%F2%E8%F6%E0");

var_dump(json_encode($decoded));
// bool(false)

var_dump(json_last_error_msg());
// string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

Как можно увидеть из ошибки: проблема с кодировкой переданной строки (это не UTF8). Решение проблемы очевидное — привести значение в UTF8

$decoded = urldecode("%EF%F2%E8%F6%E0");
$utf8 = utf8_encode($decoded);

echo json_encode($utf8);
// "ïòèöà"
Цифровые значения

Последняя типовая ошибка связана с кодированием числовых значений.

Например:
echo json_encode(["string_float" => "3.0"]);
// {"string_float":"3.0"}

Как известно php не строго типизированный язык и позволяет использовать числа в виде строки, в большинстве случаев это не приводит к ошибкам внутри php приложения. Но так как json очень часто используется для передачи сообщений между приложениями, такой формат записи числа может вызвать проблемы в другом приложении. Желательно использовать флаг JSON_NUMERIC_CHECK:

echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK);
// {"string_float":3}

Уже лучше. Но как видим «3.0» превратилось в 3, что в большинстве случаев будет интерпретировано как int. Используем еще один флаг JSON_PRESERVE_ZERO_FRACTION для корректного преобразования в float:

echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK | JSON_PRESERVE_ZERO_FRACTION);
// {"string_float":3.0}

Прошу также обратить внимание на следующий фрагмент кода, что иллюстрирует ряд возможных проблем с json_encode и числовыми значениями:

$data = [
"0000021", // нули слева
6.12345678910111213, // много знаков после точки (будет округленно)
"+81011321515", // телефон
"21E021", // экспоненциальная запись
];

echo json_encode($data, JSON_NUMERIC_CHECK);
//[
//    21,
//    6.1234567891011,
//    81011321515,
//    2.1e+22
// ]

Смотрите также: json_decode().

Описание на ru2.php.net
Описание на php.ru

.

Популярное:


Содержание: