PHP json_decode () повертає NULL з дійсним JSON?


104

Цей об’єкт JSON зберігається у простому текстовому файлі:

{
    "MySQL": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "DatabaseName": "(dbname)"
    },
    "Ftp": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "RootFolder": "(rf)"
    },
    "BasePath": "../../bin/",
    "NotesAppPath": "notas",
    "SearchAppPath": "buscar",
    "BaseUrl": "http:\/\/montemaiztusitio.com.ar",
    "InitialExtensions": [
        "nem.mysqlhandler",
        "nem.string",
        "nem.colour",
        "nem.filesystem",
        "nem.rss",
        "nem.date",
        "nem.template",
        "nem.media",
        "nem.measuring",
        "nem.weather",
        "nem.currency"
    ],
    "MediaPath": "media",
    "MediaGalleriesTable": "journal_media_galleries",
    "MediaTable": "journal_media",
    "Journal": {
        "AllowedAdFileFormats": [
            "flv:1",
            "jpg:2",
            "gif:3",
            "png:4",
            "swf:5"
        ],
        "AdColumnId": "3",
        "RSSLinkFormat": "%DOMAIN%\/notas\/%YEAR%-%MONTH%-%DAY%\/%TITLE%/",
        "FrontendLayout": "Flat",
        "AdPath": "ad",
        "SiteTitle": "Monte Maíz: Tu Sitio",
        "GlobalSiteDescription": "Periódico local de Monte Maíz.",
        "MoreInfoAt": "Más información aquí, en el Periódico local de Monte Maíz.",
        "TemplatePath": "templates",
        "WeatherSource": "accuweather:SAM|AR|AR005|MONTE MAIZ",
        "WeatherMeasureType": "1",
        "CurrencySource": "cotizacion-monedas:Dolar|Euro|Real",
        "TimesSingular": "vez",
        "TimesPlural": "veces"
    }
}

Коли я намагаюся його розшифрувати json_decode(), він повертає NULL. Чому? Файл читабельний (я намагався повторювати, file_get_contents()і він спрацював нормально).

Я протестував JSON на http://jsonlint.com/, і він цілком дійсний.

Що тут не так?

Рішення

Шукаючи відповіді в Google, я повернувся до SO: json_decode повертає NULL після виклику веб-сервісу . Мій файл JSON мав послідовність UTF BOM (деякі двійкові символи, яких там не повинно бути), таким чином, порушуючи структуру JSON. Пішла в редактор Hex, стерла байти. Все повернулося до норми. Чому це сталося? Тому що я редагував файл за допомогою блокнота Microsoft Windows. Страшна ідея!


5
Робота з PHP 5.2.9; таким чином, я не можу використовувати json_last_error().
Джоель А. Вільяреаль Бертольді

1
Також зауважте, що це може статися з іншими недійсними символами в середині файлу. Я просто мав json_decode (), що повертає null, тому що рядок містив одну з цих спеціальних en-тире, ймовірно, вставлений з MS Word, а потім, можливо, неправильно закодований. Щоб визначити потенційних проблемних символів, відкрийте файл JSON (я використовувався в Notepad ++), змініть кодування (без перетворення) та збережіть як копію. Потім розрізняйте два файли (я використовував WinMerge).
ЛінусР

(Windows Notepad випуск) Будь ласка, зверніться до цього, я теж поділяє цю проблему і встановив її: stackoverflow.com/questions/10290849 / ...
Фелікс Aballi


Для мене це не було нічого особливого, лише зайва кома в кінці елемента об’єкта. Забирайте: все, що робить ваш JSON непослідовним, призведе до помилки. Порада про бонуси: не довіряйте jsonviewer.stack.hu Використовуйте щось на зразок jsonlint
Aman Alam

Відповіді:


68

Це може бути кодування спеціальних символів. Ви можете попросити json_last_error () отримати певну інформацію.

Оновлення: питання вирішено, дивіться у пункті "Рішення" у питанні.


Я використовую спеціальні символи з моменту запуску програми, і раніше проблем не було. Місцево декодування JSON працює чудово. На моєму сервері цього немає. І я не можу дзвонити, json_last_error()оскільки це PHP 5.2.9. Ця функція з’являється на PHP 5.3.0.
Джоель А. Вільяреаль Бертольді

1
Ні, це має працювати. Я не можу зробити більше тестування зараз, якщо я дістанусь до нього пізніше, я опублікую тут. Існує також декілька підказок у користувальницьких замітках: de.php.net/json_decode можливо щось допомагає.
Pekka

1
Для мене на PHP 5.3 він працює добре, коли текст кодується в UTF-8. Але якщо я передаю текст utf8_decode()спочатку, то json_decode()мовчки не вдається.
Матвій

1
@Pekka шукають відповіді на Google, я повернувся до так: stackoverflow.com/questions/689185/json-decode-returns-null-php . Мій файл JSON мав послідовність UTF BOM (деякі двійкові символи, яких там не повинно бути), таким чином, порушуючи структуру JSON. Пішла в редактор Hex, стерла байти. Все повернулося до норми. Чому це сталося? Тому що я редагував файл, використовуючи Micro $ oft Windows 'Notepad. Страшна ідея!
Джоель А. Вільярреаль Бертольді

2
Про це слід повідомити як про помилку людям PHP. Якщо BOM був дійсним UTF8, він не повинен душити його мовчки.
jmucchiello

86

Це працювало для мене

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );

2
Я використав це і отримав масив, але мої символи, характерні для мови (ş, ç, ö, ..), також були видалені.
zkanoca

5
Це невірно, якщо дані json кодуються UTF-8 (або, мабуть, будь-яке кодування UTF). Це видалить дійсні дані, закодовані UTF-8. Це, ймовірно, буде працювати, поки файл містить лише англійську мову, але це завжди ризиковане припущення. Я б не користувався цим.
DaedalusAlpha

З цим воно працює, але без цього не виходить, навіть якщо дві струни однакові, я щось пропускаю?
Rudie Visser

це працює! але чому? рядок, який я намагався розшифрувати, не мав у ньому жодних спеціальних символів
Tobias Gassmann

Дивовижно. Працювали для мене. :)
Сохіль

31

Ви можете спробувати з цим.

json_decode(stripslashes($_POST['data']))

Я випадково зателефонував stripslashes()двічі, що видалив суттєві косої риски і спричинив невірний рядок JSON Ця відповідь допомогла мені помітити помилку
Філіпп

22

Якщо ви перевірите запит у chrome, ви побачите, що JSON - це текст, тому до JSON додано порожній код.

Ви можете очистити це за допомогою

$k=preg_replace('/\s+/', '',$k);

Тоді ви можете використовувати:

json_decode($k)

print_r потім покаже масив.


Дякую за це - сподіваємось, ви знайдете свою відсутніх англійську мову.
Dean_Wilson

Людина, ти легенда, цілий день з цим замислюється.
Sboniso Marcus Nzimande

Зробив це для мене !! Простий твіт, який я зробив, - це додавання місця в заміну, я використовую це, і, здається, замінює і мій простір. працює нормально зараз. $k=preg_replace('/\s+/', ' ',$k);
Каш

Проблема полягає в тому, що це видаляє кожен простір, завдяки чому текст англійської мови весь склеєний, чи не так?
CodeGuru

14

У мене була така ж проблема, і я вирішив її просто замінивши символ цитати перед декодуванням.

$json = str_replace('"', '"', $json);
$object = json_decode($json);

Моє значення JSON було створено функцією JSON.stringify.


У цьому випадку можливо використовується функція htmlspecialchars, і JSON більше не можна розбирати. Щоб повернути його назад, існує функція "htmlspecialchars_decode" замість ручної заміни & quot;
Деві

11

Можливо, деякі приховані персонажі возиться з вашим json, спробуйте це:

$json = utf8_encode($yourString);
$data = json_decode($json);

Спробувавши всі рішення вище, цей нарешті працював для мене. Дякую тони !!
Аніс Р.


4

Просто думав, що я додам це, коли я сьогодні зіткнувся з цим питанням. Якщо на вашому рядку JSON є оббивка рядків, json_decode поверне NULL.

Якщо ви витягуєте JSON з іншого джерела, ніж змінна PHP, було б розумно спочатку "обрізати" його:

$jsonData = trim($jsonData);

4

це допоможе вам зрозуміти, який тип помилки

<?php
// A valid json string
$json[] = '{"Organization": "PHP Documentation Team"}';

// An invalid json string which will cause an syntax 
// error, in this case we used ' instead of " for quotation
$json[] = "{'Organization': 'PHP Documentation Team'}";


foreach ($json as $string) {
    echo 'Decoding: ' . $string;
    json_decode($string);

    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
    }

    echo PHP_EOL;
}
?>

2

Просто збережіть один раз. Я витратив 3 години, щоб з’ясувати, що це просто проблема кодування HTML. Спробуйте це

if(get_magic_quotes_gpc()){
   $param = stripslashes($row['your column name']);
}else{
  $param = $row['your column name'];
}

$param = json_decode(html_entity_decode($param),true);
$json_errors = array(
JSON_ERROR_NONE => 'No error has occurred',
JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
JSON_ERROR_SYNTAX => 'Syntax error',
);
echo 'Last error : ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
print_r($param);

1

Як заявив Jürgen Math, використовуючи метод preg_replace, перерахований користувачем2254008, це виправлено і для мене.

Це не обмежується Chrome, воно, як видається, є проблемою перетворення набору символів (принаймні, в моєму випадку, Unicode -> UTF8) Це вирішило усі проблеми, які у мене виникли.

Як майбутній вузол, JSON Object i, який розшифровував, походить від функції json.dumps Python. Це, в свою чергу, спричинило внесення деяких інших антисанітарних даних, хоча це було легко вирішено.


1

Якщо ви отримуєте json з бази даних, поставте

mysqli_set_charset($con, "utf8");

після визначення з'єднання $ con


Спасибі Томоміха. Це саме те, що відповідає всім моїм проблемам із MySQL, що містить спеціальні символи, і при перетворенні json_decode це поле виведене = null ....
KLL


1

У моєму випадку це через єдину цитату в рядку JSON.

Формат JSON приймає лише подвійні лапки для ключів і значень рядків.

Приклад:

$jsonString = '{\'hello\': \'PHP\'}'; // valid value should be '{"hello": "PHP"}'
$json = json_decode($jsonString);
print $json; // null

Я заплутався через синтаксис Javascript. У Javascript, звичайно, ми можемо зробити так:

let json = {
    hello: 'PHP' // no quote for key, single quote for string value
}

// OR:
json = {
    'hello': 'PHP' // single quote for key and value
}

але пізніше при перетворенні цих об'єктів у рядок JSON:

JSON.stringify(json); // "{"hello":"PHP"}"

0

Я вирішив цю проблему, надрукувавши JSON, а потім перевіривши джерело сторінки (CTRL / CMD + U):

print_r(file_get_contents($url));

Виявилося, що з'явилася остання <pre>мітка.


0

ви повинні забезпечити ці пункти

1. у рядку json у вас немає невідомих символів

2. Рядок json може переглядати онлайн-переглядач json (ви можете шукати в Google як онлайн-переглядач або аналізатор json), він повинен переглядати без жодної помилки

3. у вашій строці немає HTML-сутностей, це повинен бути звичайний текст / рядок

для пояснення пункту 3

$html_product_sizes_json=htmlentities($html);
    $ProductSizesArr = json_decode($html_product_sizes_json,true);

для (видалення htmlentities () функції)

$html_product_sizes_json=$html;
    $ProductSizesArr = json_decode($html_product_sizes_json,true);

0

Для мене мені довелося вимкнути error_reporting , щоб json_decode () працював правильно. Це звучить дивно, але правда в моєму випадку. Оскільки між рядком JSON друкується повідомлення, яке я намагаюся розшифрувати.


0

Найголовніше, що потрібно пам’ятати, коли ви отримуєте NULL результат із дійсних даних JSON, це використовувати таку команду:

json_last_error_msg();

Тобто

var_dump(json_last_error_msg());
string(53) "Control character error, possibly incorrectly encoded"

Потім ви виправите це за допомогою:

$new_json = preg_replace('/[[:cntrl:]]/', '', $json);

0

Отже, html_entity_decode () працював на мене. Спробуйте це.

$input = file_get_contents("php://input");
$input = html_entity_decode($input);
$event_json = json_decode($input,true);

-5
<?php 
$json_url = "http://api.testmagazine.com/test.php?type=menu";
$json = file_get_contents($json_url);
$json=str_replace('},

]',"}

]",$json);
$data = json_decode($json);

echo "<pre>";
print_r($data);
echo "</pre>";
?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.