はじめに
Heroku Postgreに対して外部から(Herokuアプリ外のサービスから)データを挿入したいという状況の時、
Hasuraはとても役に立ちます。
今回は、そのPOST操作(SQLのINSERT操作)を行おうとしたときに出会った魑魅魍魎を紹介しようと思います。
Hasuraってなに?
この記事に丸投げします。私はここから学びました。
https://qiita.com/maaz118/items/9e198ea91ad8fc624491
また、HasuraはHerokuに対して強力なサポートをしており、
ワンクリックでHeroku Postgreを利用したGraphQLサーバーを立ち上げてくれます。
https://hasura.io/learn/ja/graphql/hasura/setup/
今回実装したかった事
AndroidアプリケーションからHeroku Postgreに対してデータの挿入を行いたい
それなら、GraphQLのmutationを利用して挿入しようじゃないか
おっと
今回発行するGraphQL Queryは以下のような感じだ。keyの命名と値の型の対応がおかしいだろという意見は最もだが、
主題ではないので無視してほしい。ちなみに、値は適当なものを入れている。
mutation{
insert_some_table(
objects:[
{id: 2, user_id: "2", timestamp: "2020-01-02T21:12:01", punish_id: 2, latitude: 43.123, longitude: 38.0123, car_data_id: 1, is_payment: false, image_base64: "test"}
]
){returning{id}}
}
あとはこれをPOSTするだけだーとなったわけである。
Android(Java)でPOSTリクエストを出す方法はここのコードを用いた。
http://blog.livedoor.jp/sce_info3-craft/archives/9599960.html
なので、こんな感じでJson文字列を書いてみた。
String jsonString = "{\"query\":\"mutation{insert_warn_info(objects:[{id:3,user_id:\"2\",timestamp:\"2021-01-02T21:12:01\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\"test\"}])}\"}";
そうしたらエラー発生
W/System.err: org.json.JSONException: Unterminated object at character 61 of {"query":"mutation{insert_warn_info(objects:[{id:3,user_id:"2",timestamp:"2021-01-02T21:12:01",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:"test"}])}"}
あれ?エスケープはできてるんじゃないんですか奥さん?
今回の馬鹿
今回のJSONの構成は{"query": "GraphQL Query"}という形になっている。
さて、GraphQL Queryには文字列をダブルクォーテーションで指定しなければならない部分があるわけだ。
そして、エスケープは""の1つ下のネスト毎に1回外されるという法則がある。
元々このjsonStringは文字列としてダブルクォーテーションで囲っているため、
このダブルクォーテーションを外すと、以下のようになる。
{"query":"mutation{insert_warn_info(objects:[{id:3,user_id:"2",timestamp:"2021-01-02T21:12:01",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:"test"}])}"}
jsonでコードブロックをハイライトしたのでお気づきになるだろう。そう、ダブルクォーテーションの対応がおかしいのだ。
これで解決
これはエスケープの必要があるな?ということで以下のようにする。
{"query":"mutation{insert_warn_info(objects:[{id:3,user_id:\"2\",timestamp:\"2021-01-02T21:12:01\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\"test\"}])}"}
これをjavaのStringに埋め込むためには、このエスケープ文字をエスケープする必要がある!
よって以下のようになる。
String jsonString = "{\"query\":\"mutation{insert_warn_info(objects:[{id:3,user_id:\\\"2\\\",timestamp:\\\"2021-01-02T21:12:01\\\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\\\"test\\\"}])}\"}";
user_id:\\\"2\\\"
のような感じになるということだ。
おわりに
言われればそうだが、気づかないものだ。いや、経験が足りないだけな気がするが。
同じ状況に陥った人がいるかは知らないが何かのはずみで助けになったら幸いである。