Goのインスタンスはjsonのmapとstructが変換を処理するのに便利であることを示している.
5577 ワード
今日はJSONデータ処理について簡単にお話しします.最近の仕事では、データベースデータをリアルタイムでelasticsearchに更新するため、実践の過程でJSONデータ処理の問題に遭遇しました.
リアルタイムデータ
リアルタイムデータ取得は、アリオープンソースのcanalコンポーネントによって実現され、メッセージキューkafkaを介してプロセッサに伝送される.我々が受信したJSONデータは以下のような形式である.
簡単にデータの論理を言えば、typeはデータベースイベントが新規、更新、または削除イベントであることを示し、databaseは対応するデータベース名を表し、tableは対応するテーブル名を表し、dataはデータベース内のデータである.
このJSONはどうやって処理しますか?
jsonがmapに変換
最初に思いついたのはjsonです.UnmarshalはJSONをmap[string]interface{}に変換します.
サンプルコード:
印刷結果は次のとおりです.
これで,データの解析に成功した.次はそれを使いますが、mapには通常いくつかの不足があると思います. keyによってデータを取得すると、存在しないkeyが現れる可能性があり、厳格さのためにkeyが存在するかどうかを検査する必要がある. 構造体に対する方式では、mapデータの抽出が不便でIDE補完検査が利用できず、keyが書き間違えやすい.
この場合、どのように対応すればよいでしょうか.JSONをstructに変換できれば良いのですが.
jsonをstructに変換
GOでは、jsonがstructに変換するのも便利で、変換したstructを事前に定義するだけでよい.まず変換structを定義します.
何時に説明しますか.実際のシーンでは、canalメッセージのdata構造はテーブルによって決定され、JSONが解析に成功するまで事前に知ることができないため、ここではmap[string]stringと定義する. 変換された構造体メンバーはエクスポート可能でなければならないので、メンバー変数名はすべて大文字であり、JSONとのマッピングは
解析コードは、次のように簡単です.
印刷結果:
次に、イベントタイプ取得、event.Typeで完了します.しかし、dataはまだ[]map[string]stringタイプなので、mapの問題は依然としてあります.
mapをstructに変換できますか?
mapをstructに変換
私の知る限りmapはstructに変換され、GOは内蔵されていません.実現するにはGOの反射機構に依存する必要がある.
しかし、幸いなことに、実はすでにこのことをした人がいて、バッグの名前はmapstructureで、使用もとても簡単で、それが提供したいくつかの例を叩いてマスターしました.READMEでも、このライブラリは主にJSONの一部を読み込まなければ残りのデータ構造を知ることができないシーンに遭遇し、私のシーンとこのように一致していると述べています.
インストールコマンドは次のとおりです.
使用を開始する前に、mapが変換するstruct構造、すなわちblog構造体を定義します.以下のようにします.
なぜなら、次に使用するのはmapstructureパッケージなので、struct tag識別はjsonではなくmapstructureです.
サンプルコードは次のとおりです.
eventの解析は前述と同様に,e.Tableによりblogテーブルからのデータであるか否かを判断し,もしそうであればBlog構造体を用いて解析する.次にmapstructureのDecodeで解析を完了する.
印刷結果は次のとおりです.
これで、すべての仕事が終わったようです.いや!
弱型解析
Blog構造体のすべてのメンバーがstringであり、canalが行うべきことであり、すべての値タイプがstringであるという問題を発見したかどうか分かりません.しかし、実際にはblogテーブルのuidフィールドとstateフィールドはintです.
理想的な構造体定義は以下のようにすべきである.
しかし、新しいBlogタイプを前のコードに代入すると、次のようなエラーが発生します.
プロンプトタイプの解析に失敗しました.実は、このような形式のjsonは他のいくつかのソフトタイプの言語にも現れます.
どうやってこの問題を解決しますか?2つのソリューションを提案は、int型のデータなどの使用時に変換する、strconvを使用することができる.Atoi変換. mapstructureが提供するソフトタイプmap変換structの機能を使用する.
明らかに、最初の方法はlowすぎて、変換する時にもっと多くのエラーチェックが必要です.2つ目の方法はどうですか?
サンプルコードを見ると、次のようになります.
実はmapstructureのDecodeをWeakDecodeに置き換えるだけでいいのですが、字はその意味で、弱解析です.このようにeasy.
これでやっと完成だ!次のデータ処理はずっと簡単です.mapstructureの使用を学びたいなら、ソースコードを叩く例は多くないはずです.
リアルタイムデータ
リアルタイムデータ取得は、アリオープンソースのcanalコンポーネントによって実現され、メッセージキューkafkaを介してプロセッサに伝送される.我々が受信したJSONデータは以下のような形式である.
{
"type": "UPDATE",
"database": "blog",
"table": "blog",
"data": [
{
"blogId": "100001",
"title": "title",
"content": "this is a blog",
"uid": "1000012",
"state": "1"
}
]
}
簡単にデータの論理を言えば、typeはデータベースイベントが新規、更新、または削除イベントであることを示し、databaseは対応するデータベース名を表し、tableは対応するテーブル名を表し、dataはデータベース内のデータである.
このJSONはどうやって処理しますか?
jsonがmapに変換
最初に思いついたのはjsonです.UnmarshalはJSONをmap[string]interface{}に変換します.
サンプルコード:
func main () {
msg := []byte(`{
"type": "UPDATE",
"database": "blog",
"table": "blog",
"data": [
{
"blogId": "100001",
"title": "title",
"content": "this is a blog",
"uid": "1000012",
"state": "1"
}
]}`)
var event map[string]interface{}
if err := json.Unmarshal(msg, &event); err != nil {
panic(err)
}
fmt.Println(event)
}
印刷結果は次のとおりです.
map[data:[map[title:title content:this is a blog uid:1000012 state:1 blogId:100001]] type:UPDATE database:blog table:blog]
これで,データの解析に成功した.次はそれを使いますが、mapには通常いくつかの不足があると思います.
この場合、どのように対応すればよいでしょうか.JSONをstructに変換できれば良いのですが.
jsonをstructに変換
GOでは、jsonがstructに変換するのも便利で、変換したstructを事前に定義するだけでよい.まず変換structを定義します.
type Event struct {
Type string `json:"type"`
Database string `json:"database"`
Table string `json:"table"`
Data []map[string]string `json:"data"`
}
何時に説明しますか.
json:"tagName"
のtagNameによって完了する.解析コードは、次のように簡単です.
e := Event{}
if err := json.Unmarshal(msg, &e); err != nil {
panic(err)
}
fmt.Println(e)
印刷結果:
{UPDATE blog blog [map[blogId:100001 title:title content:this is a blog uid:1000012 state:1]]}
次に、イベントタイプ取得、event.Typeで完了します.しかし、dataはまだ[]map[string]stringタイプなので、mapの問題は依然としてあります.
mapをstructに変換できますか?
mapをstructに変換
私の知る限りmapはstructに変換され、GOは内蔵されていません.実現するにはGOの反射機構に依存する必要がある.
しかし、幸いなことに、実はすでにこのことをした人がいて、バッグの名前はmapstructureで、使用もとても簡単で、それが提供したいくつかの例を叩いてマスターしました.READMEでも、このライブラリは主にJSONの一部を読み込まなければ残りのデータ構造を知ることができないシーンに遭遇し、私のシーンとこのように一致していると述べています.
インストールコマンドは次のとおりです.
$ go get https://github.com/mitchellh/mapstructure
使用を開始する前に、mapが変換するstruct構造、すなわちblog構造体を定義します.以下のようにします.
type Blog struct {
BlogId string `mapstructure:"blogId"`
Title string `mapstructrue:"title"`
Content string `mapstructure:"content"`
Uid string `mapstructure:"uid"`
State string `mapstructure:"state"`
}
なぜなら、次に使用するのはmapstructureパッケージなので、struct tag識別はjsonではなくmapstructureです.
サンプルコードは次のとおりです.
e := Event{}
if err := json.Unmarshal(msg, &e); err != nil {
panic(err)
}
if e.Table == "blog" {
var blogs []Blog
if err := mapstructure.Decode(e.Data, &blogs); err != nil {
panic(err)
}
fmt.Println(blogs)
}
eventの解析は前述と同様に,e.Tableによりblogテーブルからのデータであるか否かを判断し,もしそうであればBlog構造体を用いて解析する.次にmapstructureのDecodeで解析を完了する.
印刷結果は次のとおりです.
[{100001 title this is a blog 1000012 1}]
これで、すべての仕事が終わったようです.いや!
弱型解析
Blog構造体のすべてのメンバーがstringであり、canalが行うべきことであり、すべての値タイプがstringであるという問題を発見したかどうか分かりません.しかし、実際にはblogテーブルのuidフィールドとstateフィールドはintです.
理想的な構造体定義は以下のようにすべきである.
type Blog struct {
BlogId string `mapstructure:"blogId"`
Title string `mapstructrue:"title"`
Content string `mapstructure:"content"`
Uid int32 `mapstructure:"uid"`
State int32 `mapstructure:"state"`
}
しかし、新しいBlogタイプを前のコードに代入すると、次のようなエラーが発生します.
panic: 2 error(s) decoding:
* '[0].state' expected type 'int32', got unconvertible type 'string'
* '[0].uid' expected type 'int32', got unconvertible type 'string'
プロンプトタイプの解析に失敗しました.実は、このような形式のjsonは他のいくつかのソフトタイプの言語にも現れます.
どうやってこの問題を解決しますか?2つのソリューションを提案
明らかに、最初の方法はlowすぎて、変換する時にもっと多くのエラーチェックが必要です.2つ目の方法はどうですか?
サンプルコードを見ると、次のようになります.
var blogs []Blog
if err := mapstructure.WeakDecode(e.Data, &blogs); err != nil {
panic(err)
}
fmt.Println(blogs)
実はmapstructureのDecodeをWeakDecodeに置き換えるだけでいいのですが、字はその意味で、弱解析です.このようにeasy.
これでやっと完成だ!次のデータ処理はずっと簡単です.mapstructureの使用を学びたいなら、ソースコードを叩く例は多くないはずです.