webの進歩は日進月歩ながら毎日進化してゆくため、気が付いたら大きく変化していることがあります。
その一つが「JSON」です。
webはリンクをクリックして次のページを表示するのが一般的です。
リンクをクリックしたら、新しいページが再表示されます。
例えば改ページリンクであっても同様です。
ところがJSONはwebを再表示せずにPHP等と非同期通信ができます。
便利なのですが、とっつきにくい特徴があります。
今回JSONを組んでいて、よくわからないエラーに振り回されましたので、忘備録として記録いたします。
JSONとはそもそも何?
JSONって知っているようでよくわからないものです。
まずはJSONのサンプルをご覧いただければ幸いです。
サンプルは、ボタンを押すと、PHP側で用意した現在時刻をHTML側へ送り返しています。
JSONのすごいところは、PHPからの値を再表示せずに受け取れる点です。
PHPと通信できるということは、PHPを経由してMYSQLからのデータ取得もできるということです。
ただ欠点は、「とにかくやり方がわかりにくい」という点です。
このわかりにくさから、仕組みを理解しておらず、今回のエラーに難儀しました。
現象はこのような感じです
現象が発生するサンプルをご参照いただければ幸いです。
現象はPHPからの戻りを受け取った後エラーになり動作しません。
SyntaxError が発生し処理が実行されませんでした。
JSONなので、HTML側の問題か、PHP側いずれかの問題だと思われます。
ただ、単純な文法エラーというわけではないため、何がいけないのかさっぱりわかりません。
それでも原因の手掛かりは「記述方法」にあります
SyntaxErrorは、記述に何かしらの問題がある場合に発生します。
そこでまずはソースを確認しました。
HTMLのソース
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>JSONテスト</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function()
{
$("#btn button").click(function ()
{
$.ajax({
url: 'adderror.php',
type: 'post',
dataType: 'json',
})
.done(function ($sts)
{
$("#result").text("JSON 処理成功しました");
$("#add").append($sts["html"]);
})
.fail(function ()
{
$('#result').text("JSON 処理失敗しました");
$('#errmsg').html(error(arguments));
console.log(arguments);
});
});
function error($args)
{
var error;
if ($args[2])
{
try
{
error = JSON.parse($args[0].responseText).error.toString();
}
catch (e)
{
error = "例外エラー(" + $args[2] + "):" + $args[0].responseText;
}
}
else
{
error = $args[1] + "(PHPのリクエストに失敗しました)";
}
return error;
}
});
</script>
<style type="text/css">
article
{
width: 800px;
margin-right: auto;
margin-left: auto;
padding-top: 30px;
padding-bottom: 30px;
text-align: center;
}
#result
{
padding: 10px;
margin-bottom: 10px;
border: 1px solid #CCC;
}
#errmsg
{
margin-bottom: 30px;
color: #F00;
}
p
{
padding-top: 20px;
padding-bottom: 20px;
border-bottom-width: 1px;
border-bottom-style: dashed;
border-bottom-color: #CCC;
}
.green
{
color: #390;
font-weight: bold;
}
</style>
</head>
<body>
<article>
<h1>JSON処理でエラーがでるパターン</h1>
<div id="result">下のボタンを押してください</div>
<div id="errmsg"></div>
<div id="btn"><button>現在時刻を表示します</button></div>
<div id="add"></div>
</article>
</body>
</html>
PHPのソース
<?php
$date = date("Y/m/d H:i:s");
$data = "<p>ただいまの時刻は<br>[ <span class=\"green\">${date}</span> ]</p>";
$sts = array("html"=>$data);
/** JSON 出力 */
echo json_encode($sts);
exit();
?>
ソースに問題があるといわれても、どう見ても問題があるように見えません。
ここで手詰まりになりました…。
さらなる情報がないかググってみたところ、気になる記事を見つけました。
JSONはUTF-8以外はすべてエラーになる
PHPから日本語テキストをJSONで返信する場合、UTF-8以外の文字コードだとすべてエラーになるというものでした。
そういえば、PHPは使っているテキストエディタのデフォルトである「Shift-JIS」で記述していました。
つまり、日本語テキストをShift-JISで記述しています。
原因はこれだと思い修正しました。
PHPの記述を次のように修正
<?php
$date = date("Y/m/d H:i:s");
$data = "<p>" . mb_convert_encoding("ただいまの時刻は", "UTF-8", "SJIS-win") . "<br>[ <span class=\"green\">${date}</span> ]</p>";
$sts = array("html"=>$data);
/** JSON 出力 */
echo json_encode($sts);
exit();
?>
日本語テキストで出力している部分「ただいまの時刻は」の文字を、mb_convert_encoding関数でUTF-8へ変換しました。
テキストエディタの文字コードをUTF-8にする方法もありますが、あとから「原因なんだっけ?」と振り返った時に、ソースにmb_convert_encodingの記述があると思い出しやすいので、あえて文字コード変換を行います。
その結果、エラーが発生しなくなりました。
そのサンプルはこちらです。
今回は、JSONのインターフェース(HTML→PHPへの情報渡し/PHP→HTMLへの情報戻し)がよくわからなかったため四苦八苦しました。
また、まさかの文字コードの影響が原因でした。
さすがに、「JSONはUTF-8以外はエラー」を知っていなけれが解決できない問題でした。
よくよくググることは大事です。
本記事がお役に立てば幸いです。