Формат JSON (от англ. JavaScript Object Notation) — это текстовый формат для передачи данных. Т.е. JSON произошел из JavaScript, но он также часто используется для передачи данных в языках Python, Ruby, PHP и Java, т.к. многие среды программирования имеют возможность читать (анализировать) и генерировать JSON.
Формат JSON подразумевает, что вы можете хранить данные в нем в файлах с расширением .json
. Кроме того, он может существовать в других форматах файлов, например, в .html
или .js
, но в них вы должны использовать JSON в виде строки, т.е. текста в кавычках. Также JSON может быть объектом, присвоенным в переменную. Такой формат легко передавать между сервером и клиентской частью, т.е. с помощью браузера.
В последнее время JSON постепенно вытесняет формат XML за счет того, что он легко читаем, компактен и требует куда меньше усилий для форматирования контента. Здесь мы рассмотрим, как можно использовать JSON, узнаем о его синтаксисе и методах для работы с этим форматом.
Синтаксис и структура
Объект JSON предполагает, что данные передаются в виде пар ключ-значение, заключенных в фигурные скобки. Например:
1
2
3
4
5
|
{ “companyName”: “Арт-гостиная”,
“birthday”: “20.05.2016”,
“city”: “Киев”,
“address”: “ул. Жилянская, 20”
}
|
Итак, формат JSON предполагает, что вы указываете сначала две фигурные скобки { }
, внутри которых записываете данные в формате ключ-значние. Ключ – это всегда строка в двойных (!и только в двойных) кавычках, а значение – либо тоже строка в двойных кавычках, либо число, либо логическое true|false
, либо null
, либо массив.
Когда вы создаёте ключи, лучше всего использовать строку с латинскими символами без пробелов, можно в Camel-синтаксисе или с нижним подчеркиванием, например: “companyName”, “company_name”, но не “company name”.
Особенности JSON
- JSON – это формат данных – он содержит только свойства, а не методы.
- JSON в обязательном порядке требует двойных кавычек, которые будут использоваться вокруг строк и имен свойств. Одиночные кавычки недействительны.
- Можно легко допустить шибки в JSON, т.к. даже одна лишняя или забытая запятая или двоеточие может привести к сбою JSON-файла, в результате чего весь ваш код перестанет работать. Имеет смысл проверять JSON с помощью приложения, такого как JSONLint.
- JSON позволяет работать со строками, числами, булевыми величинами,
null
, массивами или объектами. Причем строки записываются в двойных кавычках, а числа,true|false
иnull
– без.
Для того чтобы проще было работать с JSON, можно установить дополнительные расширения для вашего редактора кода. Например, плагин JSON snippets для Visual Studio Code позволяет преобразовывать данные в строки в процессе набора текста.
В том числе с его помощью можно создавать данные в формате json в различных языках программирования (JavaScript, TypeScript и т.д.):
Методы JavaScript для работы с JSON
JavaScript предоставляет методы для работы JSON-форматом:
JSON.stringify()
для преобразования объектов в JSON.JSON.parse()
для преобразования JSON обратно в объект.
Метод JSON.stringify()
Первый метод JSON.stringify()
мы используем для преобразования данных в различных JavaScript-форматах в строку, которая будет отвечать синтаксису JSON.
Например,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
let animals = [{
name: “Mikky”,
type: ‘dog’,
age: 3,
stock: {
price: 13.9,
isSold: true,
acsessories: [‘ball’]
}
}, {
name: “Neon”,
type: ‘cat’,
age: .5,
stock: {
price: 59.7,
isSold: false,
acsessories: null
}
}];
document.write(‘<p>’ + JSON.stringify(animals) + ‘</p>’);
|
Все пары ключ-значение теперь имеют обрамление в виде двойных кавычек, массивы остались массивами, числовые значения, значение true
, false
и null
остались без изменения.
let animals = [{
name: “Mikky”,
type: ‘dog’,
age: 3,
stock: {
price: 13.9,
isSold: true,
acsessories: [‘ball’]
}
}, {
name: “Neon”,
type: ‘cat’,
age: .5,
stock: {
price: 59.7,
isSold: false,
acsessories: null
}
}];
document.write(‘
‘ + JSON.stringify(animals) + ”);
Это простой способ использования метода JSON.stringify()
. Но у него есть еще 2 необязательных параметра:
1
|
JSON.stringify(value[, replacer[, space]])
|
Параметр replacer
метода JSON.stringify()
Параметр replacer
подразумевает использование функции или массива свойств для кодирования, который будет выбран из всех переданных значений. Например, если нет необходимости передавать или публиковать часть данных:
1
2
3
4
5
6
7
8
9
|
var info = {
companyName: “Арт-гостиная”,
birthday: “20.05.2016”,
city: “Киев”,
address: “ул. Жилянская, 20”,
numberOfEmployees: 72,
vacancy: [‘дизайнер’,‘уборщица’,‘кладовщик’]
};
console.log( JSON.stringify(info, [‘companyName’, ‘city’,‘address’]) );
|
Результат работы параметра replacer
в виде массива (для вывода console.log
заменен на document.write
):
var info = {
companyName: “Арт-гостиная”,
birthday: “20.05.2016”,
city: “Киев”,
address: “ул. Жилянская, 20”,
numberOfEmployees: 72,
vacancy: [‘дизайнер’,’уборщица’,’кладовщик’]
};
document.write(‘
‘ + JSON.stringify(info, [‘companyName’, ‘city’,’address’]) + ”);
Использование функции function(key, value)
в параметре replacer подразумевает, что мы перебираем все свойства объекта по ключу (key
) или значению (value
) в соответствии с неким условием и оставляем только те свойства, которые этому условию удовлетворяют. Например, нам нужно отсортировать фамилии только с положительным дебетом
1
2
3
4
5
6
7
8
|
let debet = [{ ‘Иванов’: 500 }, {‘Петров’: –169 }, {‘Пупкин’: 1270 }, { ‘Васильева’: –740 },
{ ‘Гущин’: –200 }];
console.log( JSON.stringify(debet, function(key, value) {
if (value < 0) {
return undefined;
}
return value;
}) );
|
Результат – 2 из 5 элементов массива:
let debet = [{
‘Иванов’: 500
}, {
‘Петров’: -169
}, {
‘Пупкин’: 1270
}, {
‘Васильева’: -740
}, {
‘Гущин’: -200
}];
document.write(‘
‘ + JSON.stringify(debet, function(key, value) {
if (value < 0) {
return undefined;
}
return value;
}) + '');
Параметр space
метода JSON.stringify()
Третий необязательный параметр метода JSON.stringify()
называется space
и указывает количество пробелов (отступов) для красивого форматирования строки в JSON-формате. Для передачи данных это необязательно, для вывода информации – будет смотреться красиво. В качестве значения параметра space можно использовать целое число или знак табуляции.
1
2
3
4
5
6
7
8
9
10
11
12
|
let address = {
country: “USA”,
details: {
state: ‘California’,
city: ‘Los Angeles’,
zipCode: 90001
}
};
console.log(“2 пробела: “ + JSON.stringify(address, null, 2));
console.log(“6 пробелов: “ + JSON.stringify(address, null, 6));
console.log(“Символ табуляции: “ + JSON.stringify(address, null, “t”));
|
Можем посмотреть в консоли на разницу в форматировании:
Метод JSON.parse()
Метод JSON.parse()
, напротив, предназначен для преобразования данных из строки в объект JavaScript.
Например, у нас есть json-файл с данными о работниках некоей фирмы (все совпадения имен-фамилий – случайны, это выдуманная фирма с выдуманными сотрудниками, email-ами и телефонами), которые необходимо вывести в виде таблицы. Содержимое JSON-файла выглядит так (кстати, очень пригодился JSONLint, т.к. при форматировании было допущено несколько ошибок):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
{
“companyName”: “Арт-гостиная”,
“birthday”: “20.05.2016”,
“city”: “Киев”,
“address”: “ул. Жилянская, 20”,
“workers”: [{
“name”: “Григорий Голобородько”,
“email”: “goloborodko1978@gmail.com”,
“phone”: “378-19-47”,
“position”: “Директор”,
“active”: “пн., ср. ,пт. 15-17-00”
}, {
“name”: “Иван Мунич”,
“email”: “munich-i@ukr.net”,
“phone”: “378-19-48”,
“position”: “Зам. директора”,
“active”: “пн., ср. ,пт.14-17-00”
}, {
“name”: “Ирина Белоголовко”,
“email”: “belogolovko.irina@bigmir.net”,
“phone”: “378-22-40”,
“position”: “Главный бухгалтер”,
“active”: “вт., ср. 14-17-00”
}, {
“name”: “Степан Ефремов”,
“email”: “efrem.st@yahoo.com”,
“phone”: “378-12-32”,
“position”: “Aрт-директор”,
“active”: “вт., ср. 10-13-00”
}
]
}
|
То есть в начале файла идёт информация о самой фирме, а затем – данные о сотрудниках в виде массива. Этот файл для начала необходимо загрузить, а затем распределить данные в div
и таблицу. Для этого в html-файле создадим простую разметку внутри body
:
1
2
|
<div id=“info”></div>
<table id=“workers”></table>
|
Затем пишем скрипт:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
var workersTable = document.getElementById(‘workers’),
info = document.getElementById(‘info’),
requestURL = ‘data.json’, //файл находится в той же папке, что и html-файл, который к нему обращается
request = new XMLHttpRequest();
request.open(‘GET’, requestURL);
request.onload = function(e) {
if (request.readyState === 4) {
if (request.status === 200) {
console.log(request.response);
var dataTable = JSON.parse(request.responseText);
getTableInfo(dataTable);
} else {
console.error(request.statusText);
}
}
};
request.onerror = function(e) {
console.error(request.statusText);
};
request.send();
function getTableInfo(data) {
info.innerHTML = `<h2>Компания: ${data.companyName}</h2>
<p>Адрес: ${data.city}, ${data.address}</p>
<p>Дата основания: ${data.birthday}</p>`;
let headerTr = document.createElement(‘tr’);
headerTr.innerHTML = `<th>ФИО</th><th>Должность</th><th>Email</th>
<th>Телефон</th><th>Приемные дни/часы</th>`;
workersTable.appendChild(headerTr);
// console.log(Array.isArray(data.workers));
data.workers.forEach(function(elem) {
let tr = document.createElement(‘tr’);
tr.innerHTML = `<td>${elem.name}</td><td>${elem.position}</td>
<td>${elem.email}</td><td>${elem.phone}</td>
<td>${elem.active}</td>`;
workers.appendChild(tr);
});
}
|
В скрипте мы сначала получаем в ответе от сервера текстовые данные, которые записываем в переменную dataTable
с помощью метода JSON.parse()
:
1
|
var dataTable = JSON.parse(request.responseText);
|
А затем вызываем в функцию getTableInfo()
, которая делает разбор данных и добавляет их в div
и таблицу. Для разбора массива мы используем метод forEach()
, а перед этим убедимся, что после JSON.parse()
у нас остался именно массив:
1
|
// console.log(Array.isArray(data.workers));//true
|
Для добавления элементов мы воспользуемся методами document.createElement()
, appendChild()
и свойством innerHTML
.
1
2
3
4
|
let tr = document.createElement(‘tr’);
tr.innerHTML = `<td>${elem.name}</td><td>${elem.position}</td>
<td>${elem.email}</td><td>${elem.phone}</td> <td>${elem.active}</td>`;
workers.appendChild(tr);
|
Обратите внимание на использование обратных кавычек и переменных вида ${var_name}
– это шаблонные литералы, добавленные в синтаксис стандарта ES6 , принесшего немало интересных фишек в JavaScript.
Сам пример вживую (открыть в новой вкладке):
Еще один пример загрузки JSON-файла вы найдете в статье с соответствующим названием “Использование AJAX для загрузки JSON-данных”.
Параметр reviver
метода JSON.parse()
Как и JSON.stringify()
, метод JSON.parse()
может быть вызван со вторым необязательным параметром reviver
(см. документацию на MDN), который представляет собой вызов функции вида function(key, value)
, последовательно перебирающей все значения JSON-строки. В функции можно по какому-либо условию отсортировать значения ключей или сами ключи и вывести несколько измененный вариант JSON-данных. Важным моментом здесь является то, что функция в конце перебирает и всю строку, поэтому желательно в функции отслеживать ключ в виде пустой строки (key===''
) во избежание неприятностей:
1
2
3
4
5
6
7
8
|
let strJson = ‘{“res1”: 15, “res2”: 48, “res3″: 3,”fio”: “Барабаш Сергей”}’,
parseWithFunc = JSON.parse(strJson, function(key, value) {
console.log(key, key === ‘fio’, value)
if (key === ”) return value;
if (typeof value === ‘string’) return value; //если значение – это строка, ничего с ней не делаем
return value * 10 + ‘ баллов’; // иначе возвращаем value * 10.
});
console.log(‘parseWithFunc = ‘, parseWithFunc)
|
В данном примере нам необходимо было для вывода информации получить JSON-данные в виде неких баллов, полученных, например, при тестировании неким человеком, поэтому числовые значения мы умножали на 10 и добавляли к результату строку “баллов”:
1
|
return value * 10 + ‘ баллов’
|
В результате получим в консоли следующий объект:
Получение данных JSON-файла с помощью jQuery
В jQuery есть специальный метод $.getJSON
, который позволяет простым способом получить информацию из внешнего источника, загрузив JSON-файл методом GET. Вы можете посмотреть пример загрузки файла с актуальными курсами валют с API Приватбанк в соответствующей статье.
Практика: отправка простой формы с помощью JSON
Рассмотрим вариант с отправкой данных в формате JSON из простой формы, в которой будет несколько полей и кнопка submit. В результате работы формы будет отправлено письмо на указанный в форме email. Поэтому имеет смысл указывать тот ящик, который вы сможете потом проверить. Отправлено письмо будет с помощью AJAX. Мы рассмотрим сначала вариант кода на чистом JavaScript.
Разметка формы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<form action=“letter.php” name=“simpleForm” id=“simpleForm”>
<p>
<label for=“first_name”>Имя:</label>
<input type=“text” name=“first_name” id=“first_name” required>
</p>
<p>
<label for=“last_name”>Фамилия:</label>
<input type=“text” name=“last_name” id=“last_name” required>
</p>
<p>
<label for=“phone”>Телефон:</label>
<input type=“tel” name=“phone” id=“phone” required>
</p>
<p>
<label for=“to”>Email:</label>
<input type=“email” name=“to” id=“to” required>
</p>
<input type=“submit” id=“submit” value=“Отправить”>
</form>
<div id=“sendMessage”></div>
|
В html-коде нужно обратить внимание на атрибут action
тега <form>
и на отсутствие у кнопки submit
атрибута name
, т.к. они в дальнейшем повлияют на восприятие JS-кода. Также в самом низу присутствует пустой тег <div id="sendMessage"></div>
, в который затем мы будем выводить сообщение об отправке формы или об ошибке.
Код JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
var sendMessage = document.getElementById(‘sendMessage’);
var form = document.getElementById(‘simpleForm’),
url = form.action;
form.onsubmit = function(e) {
e.preventDefault();
var data = {}; //переменная для сбора данных из формы
for (var i = 0, len = form.length; i < len; i++) {
var input = form[i];
if (input.name) {
data[input.name] = input.value;
}
}
var jsonStr = JSON.stringify(data); //преобразуем данные из объекта data в json-строку
console.log(data, jsonStr);
var xhr = new XMLHttpRequest();
xhr.open(‘POST’, url, true);
xhr.setRequestHeader(‘Content-Type’, ‘application/json; charset=UTF-8’);
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.status != 200) {
//alert(xhr.status + ‘: ‘ + xhr.statusText);
sendMessage.innerHTML = xhr.statusText; //выводим сообщение об ошибке
} else {
console.log(xhr.response);
//alert(xhr.responseText);
//выводим полученное от PHP-скрипта сообщение об отправке письма
sendMessage.innerHTML = xhr.responseText;
form.reset();//очищаем форму
}
}
xhr.send(jsonStr); //отсылаем строку в формате JSON
}
|
В этом скрипте мы собираем в переменную-объект data
данные в виде пар имя input = значение input
, причем только в том случае, если поле input
имеет атрибут name
. Этого атрибута не имеет только кнопка submit
, поэтому ее данные не войдут в объект data
и не будут отправлены на сервер. Для отправки мы преобразуем объект в строку в формате JSON и формируем AJAX-запрос и отправляем его на тот url
, который указан в атрибуте action
. В случае ошибки запроса выводим текст ошибки в <div id="sendMessage"></div>
, в случае успеха – выводим то сообщение, которое выдаст нам PHP-скрипт и очищаем форму.
Несколько строк с методом alert()
закомментированы. Вы можете убрать комментарии, чтобы посмотреть без консоли на данные в AJAX-запросе.
Код PHP
В php-файле мы декодируем формат JSON json_decode()
в переменную $data
а затем “разбираем” ее на отдельные переменные, причем их имена будут совпадать с именами input
-ов (атрибут name
). Затем эти переменные используем для формирования письма.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?php
$data = json_decode( file_get_contents(“php://input”) );
//print_r($data);
foreach ($data as $key=>$value) {
$$key = $value;
}
//$to .= ‘, address@gmail.com’; //Почта получателя, через запятую можно указать сколько угодно адресов
$subject = ‘Простая форма с отправкой данных на JSON’; //Заголовок сообщения
$message = ‘
<html>
<head>
<title>’.$subject.‘</title>
</head>
<body>
<p>Имя: ‘.$first_name.‘ ‘.$last_name.‘</p>
<p>Телефон: ‘.$phone.‘</p>
</body>
</html>’; //В тексте отправляемого сообщения можно использовать HTML теги
$headers = “Content-type: text/html; charset=utf-8 rn”; //Кодировка письма
$headers .= “From: простая форма на JSON <someaddress@your-domain.com>rn”; //Наименование и почта вашего сайта
mail($to, $subject, $message, $headers); //Отправка письма с помощью php-функции mail
echo “<p>Письмо отправлено. Спасибо.</p><p>Проверьте почту</p>”;
?>
|
Смотрим пример в действии:
Если вы откроете пример в новой вкладке и перед тестированием запустите консоль, то увидите примерно следующее (в зависимости от того, как заполнили поля):
Практический пример: использование JSON для генерации случайной цитаты
В примере ниже вы не будете загружать файл формата JSON или отправлять данные. Вы используете этот формат для хранения массива цитат и выбираете одну из них, генерируя случайное число с помощью Math.random()
при клике на кнопку. Код простой, но, возможно, вы придумаете ему еще какое-то применение.
See the Pen JSON Random Quote Generator by Dudley Storey (@dudleystorey) on CodePen.dark