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ł!

Joel A. Villarreal Bertoldi
źródło
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.

Pekka
źródło
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 );
Dunith Dhanushka
źródło
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']))
Gabriel Castillo Prada
źródło
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ę.

user2254008
źródło
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.

Yapp Ka Howe
źródło
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);
Albert Abdonor
źródło
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

Jürgen Math
źródło
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);
Phil LaNasa
źródło
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;
}
?>
Enrico Tempesti
źródło
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);
Samuel Kwame Antwi
źródło
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ć.

Destreyf
źródło
1

Jeśli otrzymujesz json z bazy danych, wstaw

mysqli_set_charset($con, "utf8");

po zdefiniowaniu łącza połączenia $ con

TomoMiha
źródło
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"}"
Chociaż
źródło
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.

Jeffrey Roosendaal
źródło
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);
Hassan Saeed
źródło
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.

shasi kanth
źródło
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);
Dotacja
źródło
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);
Suman Deol
źródło
-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>";
?>
user2648057
źródło