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!


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.


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 );

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']))

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.


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.


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);

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


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);

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

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);

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.


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


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

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 .


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);

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.


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);

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);

-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>";
?>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.