LoginSignup
10
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 上記サービスは追記時点でアクセスできなくなってしまいました。 

10
8
4

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
  3. You can use dark theme
What you can do with signing up
10
8