PHP json_decode () retorna NULL com JSON válido?

104

Tenho este objeto JSON armazenado em um arquivo de texto simples:

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

Quando tento decodificá-lo com json_decode(), ele retorna NULL. Por quê? O arquivo é legível (tentei ecoar file_get_contents()e funcionou bem).

Eu testei o JSON em http://jsonlint.com/ e é perfeitamente válido.

O que há de errado aqui?

Solução

Procurando respostas no Google, voltei ao SO: json_decode retorna NULL após chamada de serviço da web . Meu arquivo JSON tinha a sequência UTF BOM (alguns caracteres binários que não deveriam estar lá), quebrando assim a estrutura JSON. Foi ao Editor Hex, apagou os bytes. Tudo voltou ao normal. Por que isso aconteceu? Porque editei o arquivo usando o Bloco de notas do Microsoft Windows. Idéia terrível!

Joel A. Villarreal Bertoldi
fonte
5
Trabalhando com PHP 5.2.9; portanto, não posso usar json_last_error().
Joel A. Villarreal Bertoldi,
1
Observe também que isso pode acontecer com outros caracteres inválidos no meio do arquivo. Acabei de fazer json_decode () retornar nulo porque a string continha um daqueles travessões especiais, provavelmente colados do MS Word e talvez codificados incorretamente. Para identificar caracteres com problemas em potencial, abra o arquivo JSON (eu usei no Notepad ++), altere a codificação (sem converter) e salve como uma cópia. Em seguida, diferencie os dois arquivos (usei o WinMerge).
LinusR
(Problema com o bloco de notas do Windows) Por favor, consulte isto, eu compartilhei o problema também e ele o corrigiu: stackoverflow.com/questions/10290849/…
Felix Aballi
Para mim, não foi nada de especial, apenas uma vírgula extra no final de um elemento do objeto. Tirar: Qualquer coisa que torne seu JSON inconsistente, gerará um erro. Dica bônus: não confie em jsonviewer.stack.hu Use algo como jsonlint
Aman Alam

Respostas:

68

Pode ser a codificação dos caracteres especiais. Você pode pedir a json_last_error () para obter informações definitivas.

Atualização: O problema foi resolvido, veja o parágrafo "Solução" na pergunta.

Pekka
fonte
Tenho usado os caracteres especiais desde que iniciei o aplicativo e não havia problemas antes. Localmente, a decodificação JSON funciona perfeitamente. No meu servidor, isso não acontece. E não posso ligar json_last_error()porque é o PHP 5.2.9. Essa função aparece no PHP 5.3.0.
Joel A. Villarreal Bertoldi,
1
Nah, isso deve funcionar. Não posso fazer mais testes agora, se eu chegar mais tarde postarei aqui. Existem também algumas dicas nas notas de contribuição do usuário: de.php.net/json_decode talvez algo ajude.
Pekka,
1
Para mim, no PHP 5.3, funciona bem quando o texto está codificado em UTF-8. Mas se eu passar o texto utf8_decode()primeiro, então json_decode()falhará silenciosamente.
Mateus,
1
@Pekka Procurando respostas no Google, voltei para o SO: stackoverflow.com/questions/689185/json-decode-returns-null-php . Meu arquivo JSON tinha a sequência UTF BOM (alguns caracteres binários que não deveriam estar lá), quebrando assim a estrutura JSON. Foi ao Editor Hex, apagou os bytes. Tudo voltou ao normal. Por que isso aconteceu? Porque editei o arquivo usando o Bloco de notas do Micro $ oft Windows. Idéia terrível!
Joel A. Villarreal Bertoldi
2
Isso deve ser relatado como um bug para o pessoal do PHP. Se o BOM era UTF8 válido, ele não deveria engasgar silenciosamente.
jmucchiello,
86

Isso funcionou para mim

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );
Dunith Dhanushka
fonte
2
Eu usei isso e obtive a matriz, mas os caracteres específicos do meu idioma (ş, ç, ö, ..) também foram excluídos.
zkanoca
5
Isso não está correto se os dados json são codificados em UTF-8 (ou qualquer codificação UTF, eu acho). Ele removerá dados codificados em UTF-8 válidos. Provavelmente funcionará, desde que o arquivo contenha apenas o idioma inglês, mas essa é sempre uma suposição arriscada. Eu não usaria isso.
DaedalusAlpha
Com isso funciona, mas sem ele não, mesmo que as duas cordas sejam idênticas, estou faltando alguma coisa?
Rudie Visser
funciona! mas por que? a string que tentei decodificar não tinha caracteres especiais
Tobias Gassmann,
Impressionante. Funcionou para mim. :)
Sohil
31

Você pode tentar com isso.

json_decode(stripslashes($_POST['data']))
Gabriel Castillo Prada
fonte
Eu acidentalmente chamei stripslashes()duas vezes, o que removeu barras essenciais e causou uma string JSON inválida. Essa resposta me ajudou a identificar o erro
Philipp
22

Se você verificar a solicitação no cromo, verá que o JSON é texto, portanto, foi adicionado um código em branco ao JSON.

Você pode limpá-lo usando

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

Então você pode usar:

json_decode($k)

print_r irá então mostrar a matriz.

user2254008
fonte
Obrigado por isso - espero que você encontre o seu inglês que falta.
Dean_Wilson
Cara, você é uma lenda, brigando com isso o dia todo.
Sboniso Marcus Nzimande
Fez por mim !! Um ajuste simples que fiz foi adicionar um espaço no substituir, estou usando isso, e parece substituir o meu espaço também. funciona bem agora. $k=preg_replace('/\s+/', ' ',$k);
Kash
O problema é que isso remove todos os espaços, fazendo com que o texto em inglês fique todo grudado, não é?
CodeGuru
14

Eu tive o mesmo problema e o resolvi simplesmente substituindo o caractere de aspas antes de decodificar.

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

Meu valor JSON foi gerado pela função JSON.stringify.

Yapp Ka Howe
fonte
Neste caso, a função htmlspecialchars possivelmente está sendo usada e o JSON não pode mais ser analisado. Para reverter, existe a função "htmlspecialchars_decode" em vez de substituir manualmente & quot;
Davy
11

Talvez alguns personagens ocultos estejam bagunçando seu json, tente isto:

$json = utf8_encode($yourString);
$data = json_decode($json);
Albert Abdonor
fonte
Depois de tentar todas as soluções acima, esta finalmente funcionou para mim. Muito obrigado !!
Anis R.
7
$k=preg_replace('/\s+/', '',$k); 

fez isso por mim. E sim, testando no Chrome. Obrigado ao usuário2254008

Jürgen Math
fonte
4

Só pensei em acrescentar isso, pois me deparei com esse problema hoje. Se houver qualquer preenchimento de string em torno de sua string JSON, json_decode retornará NULL.

Se você estiver extraindo o JSON de uma fonte diferente de uma variável PHP, seria aconselhável "cortá-lo" primeiro:

$jsonData = trim($jsonData);
Phil LaNasa
fonte
4

isso ajuda você a entender qual é o tipo de erro

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

Apenas salve uma vez. Passei 3 horas para descobrir que era apenas um problema de codificação de html. Tente isto

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
fonte
1

Conforme declarado por Jürgen Math, o uso do método preg_replace listado pelo usuário2254008 corrigiu para mim também.

Isso não se limita ao Chrome, parece ser um problema de conversão de conjunto de caracteres (pelo menos no meu caso, Unicode -> UTF8). Isso corrigiu todos os problemas que eu estava tendo.

Como um nó futuro, o objeto JSON que estava decodificando veio da função json.dumps do Python. Isso, por sua vez, fez com que alguns outros dados não higiênicos fossem transmitidos, embora fosse fácil de lidar.

Destreyf
fonte
1

Se você estiver obtendo json do banco de dados, coloque

mysqli_set_charset($con, "utf8");

depois de definir o link de conexão $ con

TomoMiha
fonte
Obrigado TomoMiha. Isso é exatamente o que se encaixa em todos os meus problemas com MySQL contendo caracteres especiais e quando convertido por json_decode, esse campo específico foi gerado = null ....
KLL
1

No meu caso, é por causa da aspa simples na string JSON.

O formato JSON aceita apenas aspas duplas para chaves e valores de string.

Exemplo:

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

Eu fiquei confuso por causa da sintaxe Javascript. Em Javascript, é claro, podemos fazer assim:

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

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

mas mais tarde, ao converter esses objetos em string JSON:

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

Resolvi esse problema imprimindo o JSON e verificando a origem da página (CTRL / CMD + U):

print_r(file_get_contents($url));

Descobriu-se que havia uma <pre>etiqueta à direita .

Jeffrey Roosendaal
fonte
0

você deve garantir esses pontos

1. sua string json não tem caracteres desconhecidos

2. json string pode ser visualizado no visualizador json on-line (você pode pesquisar no google como visualizador on-line ou analisador de json), ele deve ser visualizado sem nenhum erro

3. sua string não tem entidades html, ela deve ser texto / string simples

para explicação do ponto 3

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

para (remover função htmlentities ())

$html_product_sizes_json=$html;
    $ProductSizesArr = json_decode($html_product_sizes_json,true);
Hassan Saeed
fonte
0

Para mim, eu tive que desligar o error_reporting , para fazer o json_decode () funcionar corretamente. Parece estranho, mas é verdade no meu caso. Porque há algum aviso impresso entre a string JSON que estou tentando decodificar.

shasi kanth
fonte
0

A coisa mais importante a lembrar, ao obter um resultado NULL de dados JSON válido, é usar o seguinte comando:

json_last_error_msg();

Ou seja,

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

Você então corrige isso com:

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

Então, html_entity_decode () funcionou para mim. Por favor, tente isso.

$input = file_get_contents("php://input");
$input = html_entity_decode($input);
$event_json = json_decode($input,true);
Suman Deol
fonte
-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
fonte