MySQLにて次のエラーに遭遇…
ERROR 3143 (42000): Invalid JSON path expression. The error is around character position 3.
レコードのJSON型の更新時に発生しました。
同じエラーに遭遇する人もいるはずなので、
このエラーの原因と対処法をメモしておきます。
このページの目次
MySQLではJSON型が使えて便利
MySQL5.7.8以降ではJSON型が使えます。
これが次記事で書いたように大変便利です。
▼ JSON型での配列の格納方法&使いどころ
▼ こんなことがMySQLだけで実現可能
- 配列・オブジェクトをそのまま格納可能
- 構文チェック込みでJSONを格納可能
- JSONの特定キーだけ部分的に更新可能
- JSONの特定キーの値をinc / dec
- JSON操作系関数もたくさん用意されてる
MySQLだけでオブジェクトを扱える代物。
とても便利だけど使い方には慣れが必要です。
今回のエラーもJSON型に慣れてないと困惑します。
"Invalid JSON path expression" エラーに遭遇
このエラーに遭遇した経緯はこんな感じです。
初めにJSON型カラムを含むテーブルを作りました。
▼ テーブル作成・レコード挿入のSQL例
1 2 3 4 5 6 7 8 9 10 11 12 |
/// テーブル作成 CREATE TABLE colors ( id INT PRIMARY KEY, rgba_json JSON ); ## 適当なレコードを挿入 INSERT INTO colors VALUES(1, '{ "red": 255, "green": 255, "blue": 255 }'); |
▼ そしてレコード更新しようとしたが…
1 2 3 4 |
/// JSONにキーを追加して更新 UPDATE colors SET rgba_json = JSON_SET( rgba_json, '$.alpha', 255 ) WHERE id=1; |
▼ 冒頭のエラーが発生
ERROR 3143 (42000): Invalid JSON path expression. The error is around character position 3.
不思議なのはテスト環境では問題なかったことです。
テスト環境のXAMPPではエラーが出ないのに、AWSなどの本番環境ではこのエラーが出ました。恐らくMySQLバージョンの違いが影響するのかも。
どうしてだろうと少し困惑しました。
JSONパス内のキーを " で囲ってあげればOK
解決策はとっても単純です。
以下のStackOverflowに答えがありました。
▼ Invalid JSON path expression への1つの回答
Can you try this advice from
https://dev.mysql.com/doc/refman/5.7/en/json.htmlAs mentioned previously, path components that name keys must be quoted if the unquoted key name is not legal in path expressions. Let $ refer to this value.
select JSON_EXTRACT(fieldnames, '$."example-field-1"') from tablename;
引用元 : https://stackoverflow.com/questions/35735454/mysql-json-extract-path-expression-error
ダブルクオート(")でキーを囲めばOKです。
▼ 先ほどのSQLならこのように修正する
1 2 3 4 |
/// JSONにキーを追加して更新 UPDATE colors SET rgba_json = JSON_SET( rgba_json, '$."alpha"', 255 ) WHERE id=1; |
これでエラーなしで正常更新されました。
上記コードの '$."alpha"' のようにJSONパス内のキー名をダブルクオート(")で囲ってあげないとダメです。MySQLバージョンによっては補完されるけど、基本的にクオートが安全。
忘れがちなので注意が必要かもしれません。
入れ子になった2階層以上のキーでも同様
このルールは2階層以上のキーでも変わりません。
▼ 例えば2階層のキーならこのように書く
1 2 3 4 |
/// JSONにキーを追加して更新 UPDATE colors SET rgba_json = JSON_SET( rgba_json, '$."data"."name"', 'white' ) WHERE id=1; |
上記のようにダブルクオートで囲むだけです。
このルールは '$."data"."name"' に限らず、何階層のキーパスでも同じルールになります。とりあえず二重引用符で囲っておけばOK
これさえ押さえておけば大丈夫です。
以上、"Invalid JSON path expression" の解決策でした。