LoginSignup
8

More than 5 years have passed since last update.

PHPのjson_decodeがNULLになる

Last updated at Posted at 2017-10-21

何が起きたか

どこぞのAPIで取ったJSONっぽい文字列をPHPのjson_decodeに入れてみたら、NULLが返ることがあった。

試したこと1

Online JSON Viewer (http://jsonviewer.stack.hu/) にJSONをそのまま入れてみる。
残念ながら正常に変換できてしまう。JSONの構文的には問題なさそう。

試したこと2

Best Online JSON Viewer (https://codebeautify.org/jsonviewer) にも入れてみる。
何かおかしいみたいだけど、矢印の部分には何もない。

Error: Parse error on line 1:
...ventory":"1","name":"\u3010T\u30DD\u30A4
-----------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'

試したこと3

JSON整形サービス (http://www.ctrlshift.net/jsonprettyprinter/ )に入れてみた。1

Error: Invalid \escape: line 1 column 413 (char 412)

おー、ついに具体的なヒントをゲット

答え

×(算数の掛ける記号)が\xD7にエスケープされていると、json_decode関数はエラーになる。json_last_error_msg()で返ってくる情報はJSON_ERROR_SYNTAXで、ほぼノーヒント状態で調べるのも大変だった。

掛ける記号をPHPのjson_encodeで変換すると\u00d7になる。しょうがないので\xD7\u00d7に変えてあげたらうまくいった。

$json = str_replace('\xD7', '\u00d7',$json);

追記

\xD7だけでなく\xA7なんてのも出てきて、1つ1つ退治している場合ではなかった。\xで始まる16進数2つまでなら、全部置き換えてしまう。こっちのほうが幸せになれそう。

$json = preg_replace('/\\\\x([0-9a-f][0-9a-f])/i', '\\u00$1', $json);

教訓

リンク先を見ると、\xD7はJavascript向けのエスケープでした。つまり、Javascriptで処理するために作られたJSONを横取りしてPHPで処理しようとしたから悪いんだ。APIがJavascriptで処理する前提で返しているときは、気を付けよう。

リンク


  1. 2018/5/22 上記サービスは追記時点でアクセスできなくなってしまいました。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8