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.