PHP json_decode () zwraca NULL z prawidłowym kodem JSON?


104

Mam ten obiekt JSON przechowywany w zwykłym pliku tekstowym:

{
    "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"
    }
}

Kiedy próbuję go zdekodować json_decode(), zwraca NULL. Czemu? Plik jest czytelny (próbowałem powtórzyć file_get_contents()i zadziałało dobrze).

Przetestowałem JSON na http://jsonlint.com/ i jest całkowicie poprawny.

Co tu jest nie tak?

Rozwiązanie

Szukając odpowiedzi w Google, wróciłem do SO: json_decode zwraca NULL po wywołaniu usługi sieciowej . Mój plik JSON miał sekwencję UTF BOM (kilka znaków binarnych, których nie powinno tam być), co zrywa strukturę JSON. Poszedłem do Hex Editor, skasowałem bajty. Wszystko wróciło do normy. Dlaczego tak się stało? Ponieważ edytowałem plik za pomocą Notatnika Microsoft Windows. Okropny pomysł!


5
Praca z PHP 5.2.9; w związku z tym nie mogę użyć json_last_error().
Joel A. Villarreal Bertoldi

1
Zauważ również, że może się to zdarzyć z innymi nieprawidłowymi znakami w środku pliku. Po prostu kazałem json_decode () zwracać wartość null, ponieważ ciąg zawierał jeden z tych specjalnych en-myślników, prawdopodobnie wklejony z MS Word, a następnie być może nieprawidłowo zakodowany. Aby zidentyfikować potencjalne problemy, otwórz plik JSON (użyłem w Notepad ++), zmień kodowanie (bez konwersji) i zapisz jako kopię. Następnie porównaj dwa pliki (użyłem WinMerge).
LinusR

(Problem z Notatnikiem Windows) Proszę skonsultować się z tym, podzieliłem się również problemem i naprawiłem go: stackoverflow.com/questions/10290849/ ...
Felix Aballi


Dla mnie nie było to nic specjalnego, tylko dodatkowy przecinek na końcu elementu obiektu. Na wynos: wszystko, co powoduje niespójność formatu JSON, spowoduje wyświetlenie błędu. Wskazówka bonusowa: nie ufaj jsonviewer.stack.hu Użyj czegoś takiego jak jsonlint
Aman Alam

Odpowiedzi:


68

Może to być kodowanie znaków specjalnych. Możesz poprosić json_last_error () o uzyskanie konkretnych informacji.

Aktualizacja: problem został rozwiązany, spójrz na akapit „Rozwiązanie” w pytaniu.


Używam znaków specjalnych od momentu uruchomienia aplikacji i wcześniej nie było żadnych problemów. Lokalnie dekodowanie JSON działa doskonale. Na moim serwerze tak nie jest. I nie mogę zadzwonić, json_last_error()ponieważ jest to PHP 5.2.9. Ta funkcja pojawia się w PHP 5.3.0.
Joel A. Villarreal Bertoldi

1
Nie, to powinno działać. Nie mogę teraz przeprowadzić więcej testów, jeśli dojdę do tego później, opublikuję tutaj. W notatkach dodanych przez użytkowników jest również kilka wskazówek: de.php.net/json_decode może coś pomoże.
Pekka

1
U mnie na PHP 5.3 działa dobrze, gdy tekst jest zakodowany w UTF-8. Ale jeśli utf8_decode()najpierw przepuszczę tekst , po json_decode()cichu zawodzi.
Matthew

1
@Pekka Szukając odpowiedzi w Google, wróciłem do SO: stackoverflow.com/questions/689185/json-decode-returns-null-php . Mój plik JSON miał sekwencję UTF BOM (kilka znaków binarnych, których nie powinno tam być), co zrywa strukturę JSON. Poszedłem do Hex Editor, skasowałem bajty. Wszystko wróciło do normy. Dlaczego tak się stało? Ponieważ edytowałem plik za pomocą Notatnika Micro $ oft Windows. Okropny pomysł!
Joel A. Villarreal Bertoldi

2
Powinno to zostać zgłoszone ludziom PHP jako błąd. Jeśli zestawienie komponentów było poprawne w UTF8, nie powinno się nim dławić.
jmucchiello

86

To zadziałało dla mnie

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

2
Użyłem tego i otrzymałem tablicę, ale znaki specyficzne dla mojego języka (ş, ç, ö, ..) również zostały usunięte.
zkanoca

5
Nie jest to poprawne, jeśli dane json są zakodowane w formacie UTF-8 (lub jak sądzę). Spowoduje to usunięcie prawidłowych danych zakodowanych w UTF-8. Prawdopodobnie będzie działać, o ile plik będzie zawierał tylko język angielski, ale jest to zawsze ryzykowne założenie. Nie użyłbym tego.
DaedalusAlpha

Z tym działa, ale bez niego nie, nawet jeśli dwa ciągi są identyczne, czy coś mi brakuje?
Rudie Visser,

to działa! ale dlaczego? ciąg, który próbowałem zdekodować, nie zawierał żadnych specjalnych znaków
Tobias Gassmann

Niesamowite. Pracował dla mnie. :)
Sohil

31

Mógłbyś z tym spróbować.

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

Przypadkowo zadzwoniłem stripslashes()dwa razy, co spowodowało usunięcie niezbędnych ukośników i spowodowanie nieprawidłowego ciągu JSON. Ta odpowiedź pomogła mi dostrzec błąd
Filip

22

Jeśli zaznaczysz żądanie w chrome, zobaczysz, że JSON jest tekstem, więc do JSON został dodany pusty kod.

Możesz go wyczyścić, używając

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

Następnie możesz użyć:

json_decode($k)

print_r wyświetli tablicę.


Dzięki za to - mam nadzieję, że znajdziesz brakujący angielski.
Dean_Wilson

Człowieku, jesteś legendą, walczyłeś z tym przez cały dzień.
Sboniso Marcus Nzimande

Zrobiłem to dla mnie !! Prosta zmiana, którą wprowadziłem, polega na dodaniu spacji w zastępstwie, używam tego i wydaje się, że zastępuje również moją przestrzeń. teraz działa dobrze. $k=preg_replace('/\s+/', ' ',$k);
Kash

Problem polega na tym, że to usuwa każdą pojedynczą spację, sprawiając, że tekst w języku angielskim skleja się razem, prawda?
CodeGuru,

14

Miałem ten sam problem i rozwiązałem go po prostu zastępując znak cudzysłowu przed dekodowaniem.

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

Moja wartość JSON została wygenerowana przez funkcję JSON.stringify.


W tym przypadku prawdopodobnie została użyta funkcja htmlspecialchars i nie można już analizować kodu JSON. Aby to odwrócić, istnieje funkcja „htmlspecialchars_decode” zamiast ręcznego zastępowania „
Davy

11

Może jakieś ukryte postacie mieszają się z twoim jsonem, spróbuj tego:

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

Po wypróbowaniu wszystkich powyższych rozwiązań, ten w końcu zadziałał. Wielkie dzięki !!
Anis R.

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

zrobił to dla mnie. I tak, testowanie w Chrome. Dzięki dla użytkownika2254008


4

Pomyślałem, że to dodam, ponieważ napotkałem dziś ten problem. Jeśli istnieje dopełnienie ciągu znaków otaczających ciąg JSON, json_decode zwróci NULL.

Jeśli pobierasz JSON ze źródła innego niż zmienna PHP, dobrze byłoby najpierw go „przyciąć”:

$jsonData = trim($jsonData);

4

pomoże ci to zrozumieć, jaki jest rodzaj błędu

<?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

Po prostu zaoszczędź trochę czasu. Spędziłem 3 godziny, aby dowiedzieć się, że to tylko problem z kodowaniem HTML. Spróbuj tego

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

Jak stwierdził Jürgen Math, metoda preg_replace wymieniona przez user2254008 naprawiła to również dla mnie.

Nie ogranicza się to do Chrome, wydaje się, że jest to problem z konwersją zestawu znaków (przynajmniej w moim przypadku Unicode -> UTF8). To rozwiązało wszystkie problemy, które miałem.

Jako przyszły węzeł, obiekt JSON, który dekodowałem, pochodzi z funkcji json.dumps języka Python. To z kolei spowodowało, że przedostały się inne niehigieniczne dane, chociaż można było się z nimi łatwo uporać.


1

Jeśli otrzymujesz json z bazy danych, wstaw

mysqli_set_charset($con, "utf8");

po zdefiniowaniu łącza połączenia $ con


Dziękuję TomoMiha. To jest dokładnie to, co wpisuje się wszystkie moje problemy z MySQL zawierających znaki specjalne i po przeliczeniu przez json_decode, że szczególną polu została uzyskane = null ....
KLL


1

W moim przypadku dzieje się tak z powodu pojedynczego cudzysłowu w ciągu JSON.

Format JSON akceptuje tylko podwójne cudzysłowy dla kluczy i wartości ciągów.

Przykład:

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

Jestem zdezorientowany ze względu na składnię Javascript. W Javascript oczywiście możemy zrobić tak:

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

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

ale później podczas konwersji tych obiektów na ciąg JSON:

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

0

Rozwiązałem ten problem, drukując JSON, a następnie sprawdzając źródło strony (CTRL / CMD + U):

print_r(file_get_contents($url));

Okazało się, że był końcowy <pre>tag.


0

powinieneś upewnić się, że te punkty

1. Twój ciąg json nie zawiera żadnych nieznanych znaków

2. ciąg json może wyświetlać z przeglądarki json online (możesz wyszukiwać w Google jako przeglądarkę online lub parser dla json), powinien wyświetlać bez żadnego błędu

3. Twój ciąg nie ma jednostek html, powinien to być zwykły tekst / ciąg

wyjaśnienie punktu 3

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

to (usuń funkcję htmlentities ())

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

0

U mnie musiałem wyłączyć error_reporting , aby json_decode () działało poprawnie. Brzmi dziwnie, ale prawda w moim przypadku. Ponieważ między ciągiem JSON, który próbuję zdekodować, znajduje się informacja.


0

Najważniejszą rzeczą do zapamiętania, gdy uzyskasz wynik NULL z danych JSON, który jest prawidłowy, jest użycie następującego polecenia:

json_last_error_msg();

To znaczy.

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

Następnie napraw to za pomocą:

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

0

Więc html_entity_decode () zadziałało dla mnie. Spróbuj tego.

$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>";
?>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.