cpp

Получение данных в формате JSON

Хорошей альтернативой использования XML-документа для обмена данными с сервером служит использование формата JSON (JavaScript Object Notation). XML-документ из предыдущего примера можно представить в формате JSON следующим образом:

var json = '{' +
'"txt1": "Поле 1 – Строка 1", ' +
'"txt2": "Поле 2 – Строка 2"' +
'}';

При использовании формата JSON следует учитывать следующие моменты:

  • JSON-данные представлены в виде строки в кодировке UTF-8;
  • имена свойств и строки заключаются в двойные кавычки;
  • значением свойства не может быть функция, только данные различных типов: числа, строки, массивы и объекты.

Чтобы преобразовать строку json в JSON-объект, достаточно обработать ее с помощью функции eval(). Функция eval() помещает JSON-объект в память интерпретатора JavaScript и возвращает ссылку на него. Для корректной работы функции eval() строку, содержащую JSON-объект, необходимо взять в круглые скобки:

var jsonObject = eval('(' + json + ')');

Получить доступ к данным можно следующим образом:

var txt1 = jsonObject.txt1;
var txt2 = jsonObject.txt2;
console.log(txt1);           // Поле 1 – Строка 1
console.log(txt2);           // Поле 2 – Строка 2

Если преобразовать не удалось, то генерируется исключение. Чтобы избежать проблем, преобразование следует выполнять внутри конструкции try...catch:

var jsonObject = null;
try {
   jsonObject = eval('(' + json + ')');
   console.log(jsonObject.txt1);        // Поле 1 – Строка 1
   console.log(jsonObject.txt2);        // Поле 2 – Строка 2
} catch (e) {
   console.log('Не удалось декодировать');
}

В современных Web-браузерах вместо функции eval() лучше использовать метод parse() объекта JSON. Формат метода:

<Объект> = JSON.parse(<Данные JSON>)

Пример преобразования:

var jsonObject = null;
try {
   if (window.JSON && window.JSON.parse) {
      jsonObject = JSON.parse(json);
   }
   else {
      jsonObject = eval('(' + json + ')');
   }
   console.log(jsonObject.txt1);        // Поле 1 – Строка 1
   console.log(jsonObject.txt2);        // Поле 2 – Строка 2
} catch (e) {
   console.log('Не удалось декодировать');
}

В качестве JSON-объекта может быть указан массив с данными:

var json = '["Элемент1", "Элемент2", "Элемент3", "Элемент4"]';
var jsonObject = JSON.parse(json);
console.log( jsonObject[0] ); // Выведет: Элемент1

Кроме того, JSON-объект может иметь сложную структуру. Например, он может быть массивом объектов:

var json = '[ {"txt1": "Поле 1", "txt2": "Поле 2"}, ';
json += '{"text3": "Поле 3", "text4": "Поле 4"} ]';
var jsonObject = JSON.parse(json);
console.log( jsonObject[1].text3 ); // Выведет: Поле 3

Или объектом, значения свойств которого являются массивами:

var json = '{ "elem1": [1, 2, 3], "elem2": [4, 5, 6] }';
var jsonObject = JSON.parse(json);
console.log( jsonObject.elem2[0] ); // Выведет: 4

Можно также комбинировать различные варианты:

var json = '{ "elem1": [{ "txt1": "Текст1", "txt2": "Текст2" }, 2] }';
var jsonObject = JSON.parse(json);
console.log(jsonObject.elem1[0].txt2); // Выведет: Текст2

Преобразовать объект в строку в формате JSON позволяет метод stringify(). Формат метода:

<Строка> = JSON.stringify(<Объект>[, <Функция или массив>[, <Формат>]])

В первом параметре задается объект, преобразуемый в строку в формате JSON:

var obj = { "id": 10, "name": "Петр", "status": true };
var json = JSON.stringify(obj);
console.log(json);
// {"id":10,"name":"Петр","status":true}
console.log(typeof json);
// string

Во втором параметре можно указать массив с именами свойств подлежащих преобразованию:

var obj = { "id": 10, "name": "Петр", "status": true };
var json = JSON.stringify(obj, ["id", "status"]);
console.log(json); // {"id":10,"status":true}

Если во втором параметре указать ссылку на функцию, то в нее будут передаваться два параметра: название свойства и его значение. Внутри функции нужно вернуть новое значение. Если функция возвращает значение undefined, то свойство не попадет в итоговую строку:

var obj = { "id": 10, "name": "Петр", "status": true };
var json = JSON.stringify(obj, function(key, value) {
   if (key === "name") return undefined;
   return value;
});
console.log(json); // {"id":10,"status":true}

По умолчанию в строке отсутствуют какие-либо разделители между свойствами и значениями, а также отступы. Символы, используемые в качестве отступов, можно указать в параметре <Формат>. Укажем три пробела:

var obj = { "id": 10, "name": "Петр" };
var json = JSON.stringify(obj, null, '   ');
console.log(json);
// {
//    "id": 10,
//    "name": "Петр"
// }

Вместо символов можно указать число, означающее количество пробелов. Укажем один пробел:

var obj = { "id": 10, "name": "Петр" };
var json = JSON.stringify(obj, null, 1);
console.log(json);
// {
//  "id": 10,
//  "name": "Петр"
// }

Рассмотрим пример получения данных в формате JSON. Создадим документ с формой (листинг 3.10), который будет обмениваться данными с файлом ajax.php (листинг 3.11).

Листинг 3.10. Получение данных в формате JSON

<!doctype html>
<html lang="ru">
<head>
   <meta charset="utf-8">
   <meta name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
   <title>Получение данных в формате JSON</title>
</head>
<body>
<div class="container my-3">
  <form action="ajax.php" method="GET" onsubmit="return false;">
    <div class="form-group">
      <input type="text" class="form-control" id="txt1">
    </div>
    <div class="form-group">
      <input type="text" class="form-control" id="txt2">
    </div>
    <button type="button" class="btn btn-primary"
            id="btnSend">Отправить методом GET</button>
  </form>
</div>
<div class="container my-3">
   <div id="div_ajax"></div>
</div>

<script>
function processReqChange(req) {
   // Обрабатываем асинхронный запрос
   try {
      if (req.readyState == 4) {
         if (req.status == 200) { // Запрос успешно обработан
            var json = req.responseText;
            var serverData = null;
            if (window.JSON && window.JSON.parse) {
               serverData = JSON.parse(json);
            }
            else {
               serverData = eval('(' + json + ')');
            }
            var msg = serverData.txt1 + '<br>' + serverData.txt2;
            document.getElementById('txt1').value = '';
            document.getElementById('txt2').value = '';
            document.getElementById('div_ajax').innerHTML = msg;
         }
         else {
            document.getElementById('div_ajax').innerHTML = 'Ошибка';
         }
      }
   }
   catch(e) {
      document.getElementById('div_ajax').innerHTML = 'Ошибка';
   }
}

function sendReqGET() {
   // Отправка запроса методом GET
   if ( !window.XMLHttpRequest ) {
      window.alert('Ваш Web-браузер не поддерживает XMLHttpRequest');
      return;
   }
   var txt1 = document.getElementById('txt1').value;
   var txt2 = document.getElementById('txt2').value;
   if (txt1 === '' || txt2 === '') {
      window.alert('Не заполнено поле');
      return;
   }
   var url = '/ajax.php?txt1=' + encodeURIComponent(txt1);
   url += '&txt2=' + encodeURIComponent(txt2);
   // Создание объекта XMLHttpRequest
   var req = new XMLHttpRequest();
   // Подготовка асинхронного запроса методом GET
   req.open('GET', url, true);
   req.onreadystatechange = function() {
      processReqChange(req);
   };
   req.onloadstart = function() {
      document.getElementById('div_ajax').innerHTML = 'Загрузка...';
   };
   req.send(null); // Отправляем запрос
}
document.getElementById('btnSend').onclick = sendReqGET;
</script>
</body>
</html>

Листинг 3.11. Исходный код файла ajax.php

<?php
// Запрещаем кеширование
header('Expires: Tue, 12 May 2020 01:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
// Указываем MIME-тип и кодировку
header('Content-Type: application/json; charset=utf-8');
if ( isset($_GET['txt1']) && isset($_GET['txt2']) ) {
   $txt1 = htmlspecialchars($_GET['txt1'], ENT_COMPAT, 'UTF-8');
   $txt2 = htmlspecialchars($_GET['txt2'], ENT_COMPAT, 'UTF-8');
   $arr = array('txt1' => $txt1, 'txt2' => $txt2);
   echo json_encode($arr);
}
else {
   $arr = array('txt1' => 'Данные не получены', 'txt2' => '');
   echo json_encode($arr);
}

Для работы с JSON-объектами в PHP существуют две функции:

  • json_encode(<Ассоциативный массив>) — преобразует ассоциативный массив в JSON-объект;
  • json_decode(<JSON-объект>[, <Тип результата>]) — производит разбор JSON-объекта. Необязательный параметр <Тип результата> может принимать следующие значения:
  • true — результат в виде ассоциативного массива;
  • false — результат в виде объекта (значение по умолчанию).

Пример:

<?php
$arr = array();
$arr['txt1'] = 'Строка 1';
$arr['txt2'] = 'Строка 2';
$json = json_encode($arr);
$arr2 = json_decode($json);
echo $arr2->txt1, '<br>';           // Строка 1
echo $arr2->txt2, '<br>';           // Строка 2
$arr3 = json_decode($json, true);
echo $arr3['txt1'], '<br>';         // Строка 1
echo $arr3['txt2'];                 // Строка 2

Укажем тип документа в свойстве responseType и получим ответ сервера с помощью свойства response (листинг 3.12).

Листинг 3.12. Свойства responseType и response

<!doctype html>
<html lang="ru">
<head>
   <meta charset="utf-8">
   <meta name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
   <title>Свойства responseType и response</title>
</head>
<body>
<div class="container my-3">
  <form action="ajax.php" method="GET" onsubmit="return false;">
    <div class="form-group">
      <input type="text" class="form-control" id="txt1">
    </div>
    <div class="form-group">
      <input type="text" class="form-control" id="txt2">
    </div>
    <button type="button" class="btn btn-primary"
            id="btnSend">Отправить методом GET</button>
  </form>
</div>
<div class="container my-3">
   <div id="div_ajax"></div>
</div>

<script>
function onloadJSON(req) {
   try {
      if (req.status == 200) { // Запрос успешно обработан
         var json = req.response;
         var msg = json.txt1 + '<br>' + json.txt2;
         document.getElementById('txt1').value = '';
         document.getElementById('txt2').value = '';
         document.getElementById('div_ajax').innerHTML = msg;
      }
      else {
         document.getElementById('div_ajax').innerHTML = 'Ошибка';
      }
   }
   catch(e) {
      document.getElementById('div_ajax').innerHTML = 'Ошибка';
   }
}

function sendReqGET() {
   // Отправка запроса методом GET
   if ( !window.XMLHttpRequest ) {
      window.alert('Ваш Web-браузер не поддерживает XMLHttpRequest');
      return;
   }
   var txt1 = document.getElementById('txt1').value;
   var txt2 = document.getElementById('txt2').value;
   if (txt1 === '' || txt2 === '') {
      window.alert('Не заполнено поле');
      return;
   }
   var url = '/ajax.php?txt1=' + encodeURIComponent(txt1);
   url += '&txt2=' + encodeURIComponent(txt2);
   // Создание объекта XMLHttpRequest
   var req = new XMLHttpRequest();
   // Подготовка асинхронного запроса методом GET
   req.open('GET', url, true);
   req.responseType = 'json';
   req.onerror = function() {
      document.getElementById('div_ajax').innerHTML = 'Ошибка';
   };
   req.onload = function() {
      onloadJSON(req);
   };
   req.onloadstart = function() {
      document.getElementById('div_ajax').innerHTML = 'Загрузка...';
   };
   req.send(null); // Отправляем запрос
}
document.getElementById('btnSend').onclick = sendReqGET;
</script>
</body>
</html>

В этом примере мы указали тип документа в свойстве responseType:

req.responseType = 'json';

Ответ в виде JSON-объекта доступен через свойство response (ответ автоматически преобразуется из строки в объект JSON):

var json = req.response;

Учебник по jQuery и AJAX
Учебник по jQuery и AJAX в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp