GoでJSONの数字/数値を扱う
JSONはデータの表現形式です。表現はできますが、項目があるかや、型が何であるかを検査する仕組みはありません。*1
そのため、システムや実装が分かれている場合に、数値を期待しているが、JSONの表現上、数値か数字かがずれていることが起き得ます。どういうことかというと、"numeric":1234
(数値)なのか、"numeric":"1234"
(数字)なのかが違う、または不定ということ。仕様の齟齬や、実装ミスなどで発生します。
動的型付け言語の場合、よしなに扱ってくれたりしますが、Goにそれをやられると型エラーが発生してしまいます。GoでJSONを読み込む場合、encoding/jsonパッケージのjson.Unmarshal()を使って、structに読み込む方法があります。しかし、stringで定義していたら、数値がNG、int系で定義していたら、数字がNGです。
type Num struct { Number string } num := Num{} err := json.Unmarshal([]byte(`{"number":1234}`), &num) // json: cannot unmarshal number into Go struct field Num.Number of type string
type Num struct { Number int64 } num := Num{} err := json.Unmarshal([]byte(`{"number":"1234"}`), &num) // json: cannot unmarshal string into Go struct field Num.Number of type int64
Goの場合、Unmarshalで読み込めないと、黒魔術的にJSONを解析する必要がある*2ので、Unmarshalで済ませたいのです。その際に、json.Numberを使います。
使い方は簡単で、数値数字不定になっている属性の型をjson.Numberにして、そのstructを使ってUnmarshalします。そうすると数字でも数値でもabcde
などの文字列でも、Unmarshal時点ではエラーになりません。型の不一致で、JSON全体の読み込みを止めなくて済みます。もちろん使う時に数値変換は必要で、Int64()
を使いますが、数字以外の文字列の場合はエラーになります。(ParseInt失敗するのと同様)
type Num struct { Number1 json.Number Number2 json.Number Number3 json.Number } num := Num{} // Unmarshalではエラーにならない err := json.Unmarshal([]byte(`{"number1":1111,"number2":"2222","number3":"abcde"}`), &num)
// 数値はエラーにならない num1, err := num.Number1.Int64() // 数字はエラーにならない num2, err := num.Number2.Int64() // 数字以外の文字はエラー // strconv.ParseInt: parsing "abcde": invalid syntax _, err = num.Number3.Int64()
json.Number使ったUnmarshal(playground)
補足:JSON出力する時のjson.Number
json.Numberは、Marshalすると、数値として出力されます。数字、数値どちらで読み込んでいても数値になります。数以外の文字列の場合は、Marshal時にエラーになります。このjson.Numberを使って読み込んで、そのままMarshalする場合は、この数値になる動きを意識しておく必要があります。
type Num struct { Number1 json.Number `json:"number1"` Number2 json.Number `json:"number2"` } num := Num{} // 数値、数字を読み込む err := json.Unmarshal([]byte(`{"number1":1111,"number2":"2222"}`), &num) // JSONに出力 j, err := json.Marshal(num) // 数値として出力される // {"number1":1111,"number2":2222} fmt.Println(string(j))
Amazon echo (Alexa) がやってきた
スマートスピーカーが盛り上がってきてますが、Amazon echoの招待メールが来て、ポチって届きました。前の日にだいぶ購買欲落ちたってツイートしてたら、その翌日に招待メール来ました。招待メールから4日以内に注文しないと、購入権がなくなるので、注文しますよね。
ハードの感想としては、大きすぎず小さくもなく重い。350ml缶ホルダーみたいな感じです。プラグ部分は、一昔前のアダプタとまではいきませんが、少し大きなブロックぐらいはあるので、密集してると邪魔になるかも。
セットアップ
早速セットアップ
- 本体は電源コード繋いで、コンセントに挿すだけ。コードちょっと邪魔だなーという印象。上部の縁が青に光って、1分ほどでオレンジの待機状態に。
- iPhoneにAlexaアプリを入れて、amazonアカウントにログイン。
- 本体のボタンを5秒押すと、セットアップモードになって、echoがWiFiホストになるようで、iPhoneの設定からそこに接続。
- そうすると、今度はechoが接続するWiFiを選ぶ画面になって、自分のとこのWiFiを設定し、しばらくセットアップ待ち。ここで私は何回かエラー1や、登録エラーなどが発生し、詳細はヘルプを見てくださいと。ただ、ヘルプのどこだよそれはって感じで、4,5回リトライで成功。echoから少し離れた位置でやってたから失敗したのか?と思って、echoの目の前でやったら成功しました。
使ってみる
ポチった後に、echoの動画などを見ていたのと、前からGoogleのCMはOK, Googleと言ってるのを見て、掛け声の後に間を空けないとダメなのか?と思っていて、それがすごくテンポ悪くて嫌だなーと思ってました。試しに「アレクサ天気教えて」と、ひと続きで話してみたら、普通に認識したので、この懸念は払拭されてよかったです。
とりあえず、天気、ニュースを試してみた感想は、alexaが読み上げる?テキストは機械の合成音声で、単語によっては発声とテンポが聞き取りづらい(抑揚とペースが一定すぎる)のがあるのと、話題と話題の間が短すぎで、話半分に聞くぐらいがまだいいかも。ニュースコンテンツなどは配信側のコンテンツっぽいので、それはそっちの品質次第。
割と便利そうなのが、音楽を流す(amazon music)、タイマー、リスト登録。*1
- 音楽はジャズを流してみたいなのでサラッと流れてくるので、ちょっと気分を変えたい時に声操作は便利。
- タイマーは料理するので声だと手を使わなくて楽チン。
- リスト登録は「買い物リストにだしの素入れて」-> 「何を登録しますか?」(聞き返された)-> 「だしの素」で、追加されました。ふと買おうと思ってたものを追加するのに便利です。ただ、alexaアプリのそのリストが少し深いところにあるのが難点。
あとは、FireTVとつなごうとしたんですが、「問題が発生しています。しばらくして行ってください」と使えないので、一旦断念。試してる途中、意図せず「FireTVでYoutube再生して」-> 「よくわかんないけど、これ(なんか商品名を言った)をカートに追加しますか?」みたいな返答されて、「いいえ」回答。アプリから音声注文はまだOFFってる状態(デフォルトONだったよ!)ですが、amazonカートにもの突っ込めるのかな。
スキル
250社ぐらい初回からスキルに参加したようですが、ニュース配信や自然の音あたりで、初期のマーケットという感じ。iPhone3GSの時のAppStoreが、ちょっとしたアプリたくさんの感じだったのに似てて、これからどんどん増えてって高度になってくんだろうなーと思うと楽しみです。自分で作るのもできるようなので挑戦したいところ。野良スキル(自分だけとか仲間内だけで使える機構)ができるのかが気になる点です。
感想
iPhoneのSiriは全く使わない人ですが、Alexaはなぜか使い始めました(掛け声?)そんなに滑舌は良くないですが、昔に比べたらはるかに音声認識は進歩していて、とりあえずちょっと使う分には十分になってるのを実感しました。*2
スピーカーに話しかけるの違和感ないなと思ったんですが、普段娘(1歳)に話しかけてるのと似てたので、違和感もなかったのかなという気がします。娘には「〇〇、それとって」「〇〇、これないない(片付け)して」みたいな、まだしゃべれない一方通行やってるせいです。ちなみに娘はAlexaがニュース読んでると、あいつ誰だよみたいな反応をしてました。
友人から聞き出した、スマートホーム向けのNature Remoという製品、echo招待メール来た時は12月出荷分あったんですが、それから1日足らずで品切れになり、来年予定しかなく撃沈。一定数echo出荷されて、注文入ったのか、すぐ注文しなかったのを後悔。スマートホーム化は少し先になりそうです。娘にリモコン奪われないように、FireTV始め、家電の音声操作拡充させたいところ。早くしないと、今度は音声操作を乗っ取られそうです。*3
SF感あふれるワクワク感を抱けました。年末年始、技術的に遊ぶにはもってこいかも。そして5年ぐらいでスマホみたいにあって当たり前になりそう。
2017/12/2 追記
友人からNature Remo注文受付復活の報を受けて、無事注文完了しました。12月中旬から下旬発送予定だそうです。楽しみ。
CircleCI 2.0でGoのテスト触ってみた
CI周りを触ってみている中で、Dockerイメージが動くようになったという、CircleCI 2.0が気になったので触ってみました。ちなみに1.0も触ったことはないです。参考で見たページだと、2.0はBeta版の時期もありましたが、今は正式にリリースされています。
cstoreで試してみる
適当なプロジェクトとして、cstoreに入れてみることに。cstoreは、ライブラリとしてシンプルなのと、たまたまちょっとテスト書いてあったのでお試し対象に。
- CircleCIで、Add Project -> .circleci/config.ymlがなくて失敗
- プルリクで追加 -> 成功
の予定でしたが、Add Projectしたら、CircleCI1.0モードで動いて、一通りGoで行われるべきことが動いていました。1.0はCircleCI用の設定ファイルおかなくても、言語指定すると、ベースとなる動作(dependencyのgo get, go test ,go buildなど)が勝手に動くようです。これはこれで、ベースができてていいですね。
2.0は今の所、実行コマンドは自分で記述する必要があります。cstoreはライブラリかつ依存はシンプルだったので、go getしてgo testをやるだけの設定を作りました。
https://github.com/reiki4040/cstore/pull/2 https://github.com/reiki4040/cstore/pull/3
version: 2 jobs: build: working_directory: /go/src/github.com/reiki4040/cstore docker: - image: circleci/golang:1.9 steps: - checkout - run: go get github.com/BurntSushi/toml - run: go get gopkg.in/yaml.v2 - run: go test -v -race ./...
circleci CLIで事前確認ができるのをすっ飛ばして、プルリクしてマージして、インデントミスっているという愚。go getの追加とともに修正したのでプルリクが二つに分かれてます。
ローカルで事前確認
CircleCI 2.0はCLIを使って事前にテスト実行ができます。 インストールは公式参照
まず作成したconfig(.circleci/config.yml)をチェック。
circleci config validate
そのあと、ローカルでのテストビルド。
circleci build
実際にdocker imageを落としてきて実行してくれます。circleci/golangの1.9は400MBぐらいありました。
これを行えば、事前にチェックして、しょうもないミスは防げると思います。*1
ビルド結果
CircleCIサービス上のビルド結果は、誰でも見える*2ので、機密情報が出るようなのは避けましょう。そもそも書いてあったらPublicリポジトリの時点でアウトですが、何か外部から取ってきて出力みたいなのがあると、デバッグのつもりで漏洩しちゃいます。privateリポジトリは、見えないと思いますが扱ってないのでわからず。
通知
メールでビルドに関しての通知がきますが、Slackなどへの連携も可能です。 すべて通知するか、失敗(fail)と失敗後の成功(fixed)のみを通知するかを選べます。
Goのサンプル試して誤プルリクをやらかす
最初、公式のGoのサンプルを試してみてたんですが、fork後にコード少し改変して動かしてみるかーと思って、適当にやってたら、いつの間にか公式サンプルにプルリク出してしまっていました。びっくり。一言書いて、closeしました。
たぶんですが、CircleCIの画面上に、open pull requestと言うボタンがあり、不意にそれを押してしまって、自動でプルリクが作成されたのかなと。同様のことをしてしまったであろう人もいました。
料金
料金ページには、Linux向けは、1コンテナのシリアル実行で、月1,500分(25時間。30日で割ると約50分ぐらい)までのビルドであれば、ユーザやリポジトリの数を問わず無料(Freeプラン)で、ビルド時間が無制限になる有料プランは、$50/Month(2コンテナ, 2並列から)からのようです。*3
感想
Goでテスト書いて、それを実行するぐらいは簡単にできますね。Github認証で、すぐ試せるのも楽です。
前のCodeBuildでは、buildspec.ymlに実行する内容があり、動かすイメージはCodeBuild側の設定でした。CircleCIは、実行イメージと実行内容を.circleci/config.ymlに書いて、CircleCI側で実行マシンのスペック設定、実行の確認で少し異なります。今時点では使い込んでないので、どちらがどういいのかまでは、あまりわからず。
公式のGoサンプルでは、Goをビルドしてバイナリを作って、PostgreSQLのイメージとともに起動してテスト実行みたいな感じで作ってあったので、go testのコード単体ではなく、バイナリに対しての挙動テストも実行できるようです。*4
設定ファイル(.circleci/config.yml)が、docker composeと実行スクリプト的な役割になる感じなので、結構いろんなことができそうです。この他のコンテナを起動したりといった辺りは、CodeBuildにはないですね。
workflowの機能も付いているようなので、それも試してみたいところですが、とりあえずここまで。