Как json_decode массив json, полученный из JavaScript?

Я хочу отправить данные в кодировке строки json на серверную часть PHP. Для этого я использую параметр GET с данными json, закодированными в URL-адресе, в виде массива, подобного этому: ["mystring1","mystring2"]

Когда я сейчас пытаюсь декодировать его с помощью функции php json_decode, она возвращает null. Кроме того, использование этой входной строки вообще ничего не меняет: {"mykey":["mystring1","mystring2"]}.

Вот мой полный пример кода:

JavaScript:

var myArr = [];
myArr.push('mystring1');
myArr.push('mystring2');
window.location.href = 'example.com/index.php?myparam=' + encodeURIComponent(JSON.stringify(myArr));

Бэкэнд-сайт PHP:

$jsonStr = filter_input(\INPUT_GET, 'myparam', \FILTER_SANITIZE_STRING);
var_dump($jsonStr);
var_dump(json_decode($jsonStr, true));

Первый var_dump правильно печатает строку json, второй возвращает null. Использование флага assoc (2-й параметр json_encode) ничего не меняет.

Что я ожидал получить:

array(2) { [0]=> string(9) "mystring1" [1]=> string(9) "mystring2" }

Что на самом деле получил:

NULL

var_dump для $jsonStr возвращает мне следующее:

string(41) "["mystring1","mystring2"]"

есть ли шанс, что вы можете использовать для этого POST и вместо этого поместить JSON в тело запроса? Тогда вам не нужно кодировать его URI. В любом случае, если json_decode ничего не вернул, это, вероятно, не удалось - используйте эту функцию: php.net/manual/en/function.json-last-error-msg.php, чтобы узнать, почему.

ADyson 20.06.2018 16:53

Если вам нужна дополнительная помощь, покажите результат var_dump($jsonStr);

ADyson 20.06.2018 16:54

Используя приведенные выше примеры, ошибки нет: $jsonStr = '{"mykey":["mystring1","mystring2"]}'; var_dump(json_decode($jsonStr, true)); печатает ожидаемый результат. Единственная причина, почему это может не получиться, заключается в том, что вы не вставили строку JSON. Так что, пока мы не увидим реальный результат работы вашего $jsonStr, мы не сможем вам помочь.

feeela 20.06.2018 16:55

@feeela Это правда. Но я имел в виду, что если вы используете json_decode('["mystring1","mystring2"]');, это приведет к null.

alpham8 20.06.2018 16:57

@feeela Я подозреваю, что проблема в том, что encodeURIComponent(JSON.stringify(myArr)) приводит к %5B%22mystring1%22%2C%22mystring2%22%5D, который, конечно, не является допустимым JSON, поэтому, если сервер уже не декодировал это, возникнет проблема. Я думаю, это можно изменить, но было бы проще просто использовать POST и поместить JSON в тело (или просто использовать обычные отдельные параметры строки запроса).

ADyson 20.06.2018 16:57

@ alpham8 json_decode('["mystring1","mystring2"]'); не приводит к NULL - см. демонстрацию: eval.in/1025111

ADyson 20.06.2018 16:59

Когда я использую (улучшенный) var_dump($jsonStr);, я получаю ["mystring1","mystring2"], который выглядит странно. Конечно, это похоже на то, что FILTER_SANITIZE_STRING ломает JSON.

apokryfos 20.06.2018 16:59

@ alpham8 Нет, это не так: var_dump(json_decode('["mystring1","mystring2"]')); печатает ожидаемый массив: array(2) { [0] => string(9) "mystring1" [1] => string(9) "mystring2" }

feeela 20.06.2018 16:59

@feeela Ну, действительно, этот простой возвращает именно то, что мы ожидали. Но получение его с filter_input, похоже, вызывает ошибку. Если я посмотрю на json_last_error_msg(), он вернет syntax error, но я на 100% уверен, что это действительный json.

alpham8 20.06.2018 17:05

«Я на 100% уверен, что это действительный json», если есть синтаксическая ошибка, то все, что вы скармливаете json_decode, явно недействительно. Возможно, он изначально был действительным, но он прошел через процессы кодирования URI и фильтрации, прежде чем он добрался до json_decode, поэтому его можно было легко изменить. Поэтому, пожалуйста, расскажите нам (как уже просили), что выводит var_dump($jsonStr);? В любом случае, как я сказал ранее, отправка JSON в строке запроса не является хорошей идеей - подобные проблемы возникают часто. Я настоятельно рекомендую перейти на POST-запрос, именно так world + dog отправляет JSON.

ADyson 20.06.2018 17:09
FILTER_SANITIZE_STRING сломает JSON
apokryfos 20.06.2018 17:12

@apokryfos Ага, вот и все :-) Отправьте это в ответ, чтобы я мог дать вам решенный чек :-)

alpham8 20.06.2018 17:16
string(41) является странным, потому что напечатанная строка на самом деле имеет длину всего 25 символов ... предположительно, там также есть некоторые скрытые, пробельные или непечатаемые символы, которые не считаются допустимыми JSON. Как говорит апокирфос, это, скорее всего, результат фильтрации, которая в данном сценарии кажется ненужной задачей. Кодирование URl также является осложнением, которого можно избежать.
ADyson 20.06.2018 17:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
13
528
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ошибка здесь не в JSON, а в запросе с использованием закодированных компонентов URI.

Если вы используете encodeURIComponent на стороне JS, вам также придется использовать urldecode на стороне PHP.

<?php
$jsonStr = '%5B%22mystring1%22%2C%22mystring2%22%5D';
var_dump(
    json_decode(urldecode($jsonStr), true)
);

См .: http://php.net/manual/en/function.urldecode.php

нет, см. комментарий выше. Он уже правильно закодирован в представляющей строке.

alpham8 20.06.2018 17:17
Ответ принят как подходящий

Я передаю записку от Что делает FILTER_SANITIZE_STRING?, но весь принятый ответ на этот вопрос объясняет это намного лучше:

First - php_filter_strip. It doesn't do much, just takes the flags you pass to the function and processes them accordingly. It does the well-documented stuff.

Then we construct some kind of map and call php_filter_encode_html. It's more interesting: it converts stuff like ", ', & and chars with their ASCII codes lower than 32 and higher than 127 to HTML entities, so & in your string becomes &. Again, it uses flags for this.

Then we get call to php_strip_tags_ex, which just strips HTML, XML and PHP tags (according to its definition in /ext/standard/string.c) and removes NULL bytes, like the comment says.

(Подчеркнул важную часть).

Короче говоря, FILTER_SANITIZE_STRING сломает ваш JSON, потому что он будет кодировать то, чего не должен. Если вы хотите проверить этот ввод, не используйте этот фильтр.

Ответ здесь - не использовать FILTER_SANITIZE_STRING. Разумный способ проверить строку JSON - выполнить json_decode и проверить, является ли она нулевой.

$jsonStr = filter_input(\INPUT_GET, 'myparam'); 
var_dump($jsonStr); 
var_dump(json_decode($jsonStr, true)); 

Большое спасибо за расследование! :-)

alpham8 20.06.2018 17:27

Я настоятельно рекомендую вам использовать компонент Symphony VarDumper при отладке, потому что он будет отображать строку дословно вместо того, чтобы выгружать ее в окно браузера и позволять браузеру отображать ее как HTML.

apokryfos 20.06.2018 17:29

Что ж, спасибо за подсказку, но в некоторые из наших простых проектов на PHP невозможно интегрировать композитор. Если я подойду к той же проблеме, я буду сравнивать ее содержимое в двоичном формате в будущем. Думаю, это тоже может помочь.

alpham8 20.06.2018 17:59

Другие вопросы по теме