Отправка данных. Отправить данные JSON с Javascript на PHP? Отправка json php

  • 25.01.2024

Последнее обновление: 1.11.2015

Принцип отправки данных может отличаться в различных ситуациях. Рассмотрим эти ситуации.

Отправка GET-запроса

GET-запрос характеризуется тем, что данные могут отправляться в строке запроса:

// объект для отправки var user = { name: "Tom", age: 23 }; var request = new XMLHttpRequest(); function reqReadyStateChange() { if (request.readyState == 4) { var status = request.status; if (status == 200) { document.getElementById("output").innerHTML=request.responseText; } } } // строка с параметрами для отправки var body = "name=" + user.name + "&age="+user.age; request.open("GET", "http://localhost:8080/postdata.php?"+body); request.onreadystatechange = reqReadyStateChange; request.send();

Для отправки берем свойства объекта user и формируем из их значений сроку с параметрами: "name=" + user.name + "&age="+user.age . Затем эта строка добавляется к строке запроса в методе open("GET", "http://localhost:8080/postdata.php?"+body)

Предполагается, что данные отправляются скрипту на языке php postdata.php, который может иметь, например, следующее содержание:

Конкретная технология стороны сервера тут не важна. И в качестве тестирования можно взять любую другую технологию. Например, ASP.NET MVC. Метод контроллера в ASP.NET MVC, который принимает данные, мог бы выглядеть следующим образом:

Public string PostData(string name, int age) { return "Ваше имя: "+name +"; Ваш возраст: "+ age; }

Кодирование параметров

Все отправляемые в GET-запросе параметры разделяются знаком амперсанда(&). Но что, если какой-нибудь параметр имеет знак амперсанда. Например,

Var user = { name: "Tom&Tim", age: 23 }; // строка с параметрами для отправки var body = "name=" + user.name + "&age="+user.age;

В этом случае при получении параметров скрипт на стороне сервера может неправильно обработать данные и неправильно извлечь параметры. Поэтому, чтобы кодировать все передаваемые данные, нужно применять функцию encodeURIComponent() :

Var body = "name=" + encodeURIComponent(user.name) + "&age="+encodeURIComponent(user.age);

При этом строка "Tom&Tim" будет кодирована в следующую строку: "Tom%26Tim".

При необходимости мы можем выполнить обратное декодирование с помощью функции decodeURIComponent() :

Var encodeName = encodeURIComponent(user.name); // Tom%26Tim var decodeName = decodeURIComponent(encodeName); // Tom&Tim

POST-запросы

Отправка данных в POST-запросах будет немного отличаться:

Var user = { name: "Tom", age: 23 }; var request = new XMLHttpRequest(); function reqReadyStateChange() { if (request.readyState == 4 && request.status == 200) document.getElementById("output").innerHTML=request.responseText; } var body = "name=" + user.name + "&age="+user.age; request.open("POST", "http://localhost:8080/postdata.php"); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.onreadystatechange = reqReadyStateChange; request.send(body);

Для отправки данных методом POST надо установить заголовок Content-Type с помощью метода setRequestHeader() . В данном случае заголовок имеет значение application/x-www-form-urlencoded .

Отправка форм. FormData

Начиная со спецификации XMLHttpRequest2 в JavaScript появился новый объект - FormData , который позволяет сериализовать данные формы для ее последующей отправки. При этом нам даже необязательно создавать форму в коде html, мы можем создать ее динамически в JavaScript:

Var formData = new FormData(); formData.append("name", "Tom"); formData.append("age", 23); var request = new XMLHttpRequest(); function reqReadyStateChange() { if (request.readyState == 4 && request.status == 200) document.getElementById("output").innerHTML=request.responseText; } request.open("POST", "http://localhost:8080/display.php"); request.onreadystatechange = reqReadyStateChange; request.send(formData);

Для добавления данных у объекта FormData используется метод append("имя_параметра", значение) . При этом никакие заголовки указывать не надо.

Также мы можем определить форму в html и использовать ее для отправки:



// получаем объект формы var form = document.forms.user; // прикрепляем обработчик кнопки form.submit.addEventListener("click", sendRequest); // обработчик нажатия function sendRequest(event){ event.preventDefault(); var formData = new FormData(form); var request = new XMLHttpRequest(); request.open("POST", form.action); request.onreadystatechange = function () { if (request.readyState == 4 && request.status == 200) document.getElementById("output").innerHTML=request.responseText; } request.send(formData); }

Для сериализации всех полей формы нам достаточно передать объект формы в конструктор FormData: var formData = new FormData(form);

Отправка данных в формате json

Для отправки данных в формате json нам необходимо установить соответствующий заголовок и сериализовать данные с помощью метода JSON.stringify:

// объект для отправки var user = { username: "Tom", age: 23 }; var json = JSON.stringify(user); var request = new XMLHttpRequest(); request.open("POST", "http://localhost:8080/postjson.php"); request.setRequestHeader("Content-type", "application/json; charset=utf-8"); request.onreadystatechange = function () { if (request.readyState == 4 && request.status == 200) document.getElementById("output").innerHTML=request.responseText; } request.send(json);

Я получил много информации здесь, поэтому я хотел опубликовать решение, которое я обнаружил.

Проблема: Получение данных JSON из Javascript в браузере, на сервере и использование PHP для его успешного анализа.

Среда: Javascript в браузере (Firefox) в Windows. LAMP-сервер как удаленный сервер: PHP 5.3.2 на Ubuntu.

Что работает (версия 1):
1) JSON - это просто текст. Текст в определенном формате, но только текстовая строка.

2) В Javascript, var str_json = JSON.stringify(myObject) дает мне строку JSON.

3) Я использую объект AJAX XMLHttpRequest в Javascript для отправки данных на сервер:
request= new XMLHttpRequest()
request.open("POST", "JSON_Handler.php", true)
request.setRequestHeader("Content-type", "application/json")
request.send(str_json)
[... code to display response ...]

4) На сервере PHP-код для чтения строки JSON:
$str_json = file_get_contents("php://input");
Это считывает необработанные данные POST. $str_json теперь содержит точную строку JSON из браузера.

Что работает (версия 2):
1) Если я хочу использовать заголовок запроса "application/x-www-form-urlencoded" , мне нужно создать стандартную строку POST "x=y&a=b" , чтобы при ее получении PHP она могла помещаться в ассоциативный массив $_POST. Итак, в Javascript в браузере:

Var str_json = "json_string=" + (JSON.stringify(myObject))

Теперь PHP сможет заполнить массив $_POST, когда я отправлю str_json через AJAX/XMLHttpRequest, как в версии 1 выше.

Отображение содержимого $_POST["json_string"] отобразит строку JSON. Использование json_decode() в элементе массива $_POST с помощью строки json будет правильно декодировать эти данные и поместить их в массив/объект.

Ловушка, с которой я столкнулся:
Первоначально я попытался отправить строку JSON с заголовком приложения /x -www-form-urlencoded, а затем попытался сразу прочитать его из массива $_POST в PHP. Массив $_POST всегда был пустым. Это потому, что он ожидает данные формы yval = xval & . Он не нашел таких данных, только строку JSON, и он просто выбросил ее. Я просмотрел заголовки запросов, и данные POST были отправлены правильно.

Аналогично, если я использую заголовок application/json, я снова не могу получить доступ к отправляемым данным через массив $_POST. Если вы хотите использовать заголовок содержимого приложения /json, тогда вы должны получить доступ к необработанным данным POST в PHP через вход php://, а не с $_POST.

Литература:
1) Как получить доступ к данным POST в PHP: Как получить доступ к данным POST на PHP?
2) Подробная информация о типе application/json с некоторыми образцовыми объектами, которые могут быть преобразованы в строки JSON и отправлены на сервер:

Как отправить Ajax’ом список объектов (List) в JSON формате

Пример 1 $(document).ready(function () { $("body").on("click", "button", function () { var product = JSON.stringify({ "Name": $("textarea").val(), "Cost": $("input").val(), }); console.log(product); $.ajax({ url: "/Products/AjaxCreate/", method: "POST", contentType: "application/json", data: product, success: function (response) { console.log(response); } }); }); });

Контроллер

Public ActionResult AjaxCreate(Product product){ return Json(new { result = "success" }, JsonRequestBehavior.AllowGet); }

Пример 2 //Сохранение накладной $("body").on("click", "button", function () { //Соберем таблицу как массив объектов var billDetails = ; $(".item").each(function () { var name = $(this).find(".name").val(); //Название var quantity = parseInt($(this).find(".quantity").val()); //Количество var price = parseFloat($(this).find(".price").val());//Цена var summ = parseFloat($(this).find(".item-summ").attr("value"));//Сумма var productId = parseFloat($(this).find(".item-id").attr("value"));//Id Товара var productSkuId = parseInt($(this).find(".item-sku-id").attr("value"));//Id Торгового предложения Товара var notRec = $(this).find(".item-not-rec").prop("checked");//Учитывать товар или нет billDetails.push({ Name: name, Quantity: quantity, Price: price, Summ: summ, ProductId: productId, ProductSkuId: productSkuId, NotRec: notRec }); }); console.log(billDetails); billDetails = JSON.stringify({ "billDetails": billDetails }); //Превратим в Стетхема //Отправим на сохранение $.ajax({ url: "/Bills/AjaxSaveInvoiceBill/", method: "POST", contentType: "application/json", data: billDetails, success: function (response) { window.location.replace("/Bills/List/"); } }); return false; });

Контроллер

Public ActionResult AjaxSaveInvoiceBill(List billDetails){ if (billDetails.Count == 0) return Json(new { result = "error", message = "В накладной нет товаров" }, JsonRequestBehavior.AllowGet); //Создадим новую приходную накладную, получим ее ID long billId = Bill.CreateBill(BillTypes.Invoice); //Теперь сохраним каждую позицию под ID новой накладной BillDetail.SaveBillDetails(billDetails, billId); return Json(new { result="success", message="Накладная успешно создана" }, JsonRequestBehavior.AllowGet); }

Ajax запрос в контроллер и получение Json ответа $(document).ready(function () { $.ajax({ url: "/Suppliers/AjaxGetSuppliersList/", method: "GET", success: function (response) { data = JSON.stringify(response.suppliers); var list = eval("(" + data + ")"); suggest_count = list.length; if (suggest_count > 0) { $(".supplier-select").empty();//Очистим список элементов //полученный список элементов добавим в селект $.each(response.suppliers, function (key, value) { $(".supplier-select").append("" + value.Name + ""); }); } } }); });

Контроллер

Public ActionResult AjaxGetSuppliersList() { List suppliers = Supplier.GetSuppliers(); return Json(new { suppliers }, JsonRequestBehavior.AllowGet); }

Отправка и получение данных в формате JSON с использованием метода POST // Sending and receiving data in JSON format using POST method // var xhr = new XMLHttpRequest(); var url = "url"; xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var json = JSON.parse(xhr.responseText); console.log(json.email + ", " + json.password); } }; var data = JSON.stringify({"email": "hey ", "password": "101010"}); xhr.send(data); Отправка принимаемых данных в формате JSON с использованием метода GET // Sending a receiving data in JSON format using GET method // var xhr = new XMLHttpRequest(); var url = "url?data=" + encodeURIComponent(JSON.stringify({"email": " ", "password": "101010"})); xhr.open("GET", url, true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { var json = JSON.parse(xhr.responseText); console.log(json.email + ", " + json.password); } }; xhr.send(); Обработка данных в формате JSON на стороне сервера с помощью PHP

Предел длины запроса HTTP Get зависит от используемого сервера и клиента (браузера) от 2kB - 8kB. Сервер должен вернуть 414 (Request-URI Too Long) статус, если URI больше, чем сервер может обрабатывать.

Примечание. Кто-то сказал, что я могу использовать имена состояний вместо значений состояния; другими словами, я мог бы использовать xhr.readyState === xhr.DONE вместо xhr.readyState === 4 Проблема в том, что Internet Explorer использует разные имена состояний, поэтому лучше использовать значения состояния.

Мне нужно отправить JSON (который я могу выполнить) на сервер и получить полученный JSON на стороне пользователя, не используя JQuery.

Если я должен использовать GET, как передать JSON в качестве параметра? Есть ли риск, что это будет слишком долго?

Если я должен использовать POST, как установить эквивалент функции onload в GET?

Или я должен использовать другой метод?

Замечание

Этот вопрос заключается не в отправке простого AJAX. Он не должен быть закрыт как дубликат.

JSON (JavaScript Object Notation) – формат для обмена данными в текстовом виде. Позволяющий передавать сложные структуры данных в сериализованном виде. Этот формат передачи данных стал настолько популярен, что уже в ядро PHP начиная с версии 5.2.0, были добавлены функции по обработке данных в этом формате. А это значит, что нет необходимости в подключении дополнительных расширений. Формат данных JSON хорошо понятен человеку. Кроме того данный тип обмена данными широко используется между различными API сервисами. А при корректной разработке алгоритмов для обмена информацией, можно получить очень высокий прирост скорости чем, к примеру, при работе с данными в формате XML .

Отправка данных

Отправить данные в формате JSON можно двумя способами: сформировать GET или POST запрос с закодированными данными расположенными в GET или POST переменной или же поместить данные в тело документа. На практике обычно используется второй вариант.

Для произведения отправки данных необходимы нижеперечисленные функции:

  • string json_encode (mixed value [, int options = 0 ])

    В качестве параметра value указываются данные которые требуется закодировать. Поддерживается любой тип кроме типа resource . Параметр options содержит битовую маску из возможных предоставленных значений (см. таблицу с предоставленными JSON константами).

  • resource stream_context_create (])

    Данная функция предназначена для создания и возврата контекста потока с опциями указанными в параметре options . Необязательный параметр options должен иметь тип ассоциативного массива. Изначально, он пуст. Второй необязательный параметр params также должен являться ассоциативным массивом в формате $data[‘имя’] = значение.

  • string file_get_contents (string filename [, bool use_include_path [, resource context [, int offset [, int maxlen ]]]])

    Использование этой функции позволяет получить содержимое файла в виде строки. Параметр filename это имя считываемого файла. В параметре use_include_path начиная с версии PHP 5 можно использовать константу FILE_USE_INCLUDE_PATH для поиска файла в include path. Параметр context представляет ресурс контекста, созданный с помощью функции stream_context_create(). В случае неудавшейся попытки открытия файла, будет возвращено значение false . Параметр offset содержит смещение с которого начнется чтение данных. В параметре maxlen указывается размер получаемых данных.

    Примечание : смещение не указывается при работе, с удаленными потоками.

Ниже приведен пример отправки данных в формате JSON:

// Данные для отправки $request = array("StartDate" => "2013-10-10", "EndDate" => "2013-10-10", "IDS" => array(1,2,3,4,5,6,7)); // Указание опций для контекста потока $options = array ("http" => array ("method" => "POST", "header" => "Content-Type: application/json; charset=utf-8\r\n", "content" => json_encode($request))); // Создание контекста потока $context = stream_context_create($options); // Отправка данных и получение результата echo file_get_contents("http://test.ru/json.php", 0, $context);

Здесь используется импровизированная структура данных, состоящая из начальной и конечной даты, а также массива номеров некоторых условных записей. Обратите внимание на то, что в заголовке запроса Content-Type указывается тип “application/json”.

Получение данных

Для того чтобы получить переданные данные вышеописанным способом требуется произвести чтение данных из потока ввода “php://input ”.

Используемые функции для принятия данных:

  • mixed json_decode (string json [, bool assoc = false [, int depth = 512 [, int options = 0 ]]])

    Данная функция декодирует строку в формате JSON . В параметре json указывается строка для декодирования. Параметр assoc отвечает за то, будут ли возвращаемые данные преобразованы в ассоциативный массив. Если таковая необходимость имеется, то необходимо указать в качестве значения этого параметра true . Параметр depth указывает на глубину рекурсии. И последний четвертый параметр options содержит битовую маску опций для декодирования. На сегодняшний день поддерживается только JSON_BIGINT_AS_STRING (по умолчанию большие целые числа приводятся к числам с плавающей запятой (float))

  • resource fopen (string filename , string mode [, bool use_include_path [, resource context ]])

    Открывает файл и возвращает его дескриптор. Параметр filename это именованный ресурс, указывающий на файл. В параметре mode указывается тип доступа к файлу (см. таблицу со списком возможных режимов для fopen()). Далее идут два необязательных параметра это: use_include_path и context . При установке параметра use_include_path в значение true или 1 и при условии, что в качестве именованного ресурса задан относительный путь, будет осуществлен поиск открываемого файла в списке директорий используемом функциями include и require . На практике этот параметр практически не используется. Параметр context используется для указания контекста ресурса.

  • string stream_get_contents (resource handle [, int maxlen = -1 [, int offset = -1 ]])

    Эта функция позволяет получить содержимое потока в виде строки. Параметр handle является ресурсом потока. Параметр maxlen содержит максимальное количество байт для чтения. По умолчанию он установлен в -1, что указывает на получение всех данных. Параметр offset содержит смещение, с которого начнется чтение данных. По умолчанию он также установлен в -1, что означает, что чтение будет произведено с начальной позиции.

Ниже приведен пример получения данных в формате JSON на стороне сервера:

// Открываем на чтение поток ввода $f = fopen("php://input", "r"); // Получаем содержимое потока $data = stream_get_contents($f); if ($data) { // Код обработки print_r(json_decode($data)); }

Полученная структура данных:

StdClass Object ( => 2013-10-10 => 2013-10-10 => Array ( => 1 => 2 => 3 => 4 => 5 => 6 => 7))

Примечание : необходимо учитывать тот момент, что для работы с форматом JSON, данные должны быть в кодировке utf-8.

Предоставленные JSON константы для функции json_encode()

JSON_HEX_TAG (integer) Все кодируются в \u003C и \u003E. Доступна начиная с PHP 5.3.0.
JSON_HEX_AMP (integer) Все & кодируются в \u0026. Доступна начиная с PHP 5.3.0.
JSON_HEX_APOS (integer) Все символы ‘ кодируются в \u0027. Доступна начиная с PHP 5.3.0.
JSON_HEX_QUOT (integer) Все символы " кодируются в \u0022. Доступна начиная с PHP 5.3.0.
JSON_FORCE_OBJECT (integer) Выдавать объект вместо массива при использовании неассоциативного массива. Это полезно, когда принимающая программа или код ожидают объект или же массив пуст. Доступна начиная с PHP 5.3.0.
JSON_NUMERIC_CHECK (integer) Кодирование строк, содержащих числа, как числа. Доступна начиная с PHP 5.3.3.
JSON_BIGINT_AS_STRING (integer) Кодирует большие целые числа в виде их строковых эквивалентов. Доступна начиная с PHP 5.4.0.
JSON_PRETTY_PRINT (integer) Использовать пробельные символы в возвращаемых данных для их форматирования. Доступна начиная с PHP 5.4.0.
JSON_UNESCAPED_SLASHES (integer) Не экранировать /. Доступна начиная с PHP 5.4.0.
JSON_UNESCAPED_UNICODE (integer) Не кодировать многобайтные символы Unicode (по умолчанию они кодируются как \uXXXX). Доступна начиная с PHP 5.4.0.

Список возможных режимов для fopen() используя mode

‘r’ Открывает файл только для чтения; помещает указатель в начало файла.
‘r+’ Открывает файл для чтения и записи; помещает указатель в начало файла.
‘w’ Открывает файл только для записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует — пробует его создать.
‘w+’ Открывает файл для чтения и записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует — пытается его создать.
‘a’ Открывает файл только для записи; помещает указатель в конец файла. Если файл не существует — пытается его создать.
‘a+’ Открывает файл для чтения и записи; помещает указатель в конец файла. Если файл не существует — пытается его создать.
‘x’ Создаёт и открывает только для записи; помещает указатель в начало файла. Если файл уже существует, вызов fopen() закончится неудачей, вернёт FALSE и выдаст ошибку уровня E_WARNING. Если файл не существует, попытается его создать. Это эквивалентно указанию флагов O_EXCL|O_CREAT для внутреннего системного вызова open(2).
‘x+’ Создаёт и открывает для чтения и записи; иначе имеет то же поведение что и’x’.
‘c’ Открывает файл только для записи. Если файл не существует, то он создается. Если же файл существует, то он не обрезается (в отличии от ‘w’), и вызов к этой функции не вызывает ошибку (также как и в случае с ‘x’). Указатель на файл будет установлен на начало файла. Это может быть полезно при желании заблокировать файл (смотри flock()) перед изменением, так как использование ‘w’ может обрезать файл еще до того как была получена блокировка (если вы желаете обрезать файл, можно использовать функцию ftruncate() после запроса на блокировку).
‘c+’ Открывает файл для чтения и записи; иначе имеет то же поведение, что и ‘c’.