こんにちは。KOUKIです。
とあるWeb系企業でエンジニアをやってます。
Go言語で開発することが多く、備忘のために記事をたくさん書いています。
今回は、Go言語でのJSONデータの取り扱いについて記事にしました。
<目次>
MarshalとUnMarshalの復習
以前、JsonパッケージのMarshalとUnMarshalの記事を書きました。
UnMarshalは、データ(例えばJson)をGo言語のStruct構造体に変換してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package main import ( "encoding/json" "fmt" ) type Book struct { Title string Price int } func main() { // Unmarshal - json -> go struct b := []byte(`{"title": "Harry Potter", "price": 20}`) var book Book if err := json.Unmarshal(b, &book); err != nil { fmt.Println(err) } fmt.Println(book.Title, book.Price) } |
1 2 3 |
// 実行 $ go run main.go Harry Potter 20 |
一方、MarshalはGoのStructをjsonに変換します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package main import ( "encoding/json" "fmt" ) type Book struct { Title string Price int } func main() { // Unmarshal - json -> go struct b := []byte(`{"title": "Harry Potter", "price": 20}`) var book Book if err := json.Unmarshal(b, &book); err != nil { fmt.Println(err) } fmt.Println(book.Title, book.Price) // Marshal - go struct -> json v, _ := json.Marshal(book) fmt.Println(string(v)) } |
1 2 3 4 |
// 実行 $ go run main.go Harry Potter 20 {"Title":"Harry Potter","Price":20} # marshal data |
Struct構造なしでJSONデータを扱う
今回、この記事でお伝えしたいことは、JSONデータをStruct構造体なしで取り扱う方法です。
例えば、UnMarshalの処理時に、Book Struct構造体を用意していたと思います。
1 2 3 4 |
type Book struct { Title string Price int } |
このデータは、JSONのKeyの値と一致しています。一致していないと型変換できません。
1 2 |
// keyとStructが一致している必要がある []byte(`{"title": "Harry Potter", "price": 20}`) |
しかし、例えば、Redisなどのデータベースに格納されているJSONデータをUnMarshalしたい場合はどうすればいいでしょうか?
新しいKeyが追加されるたびにプログラムを書き換えるのでしょうか?
1 2 3 4 5 6 7 8 |
// 新しい項目(review)が追加される []byte(`{"title": "Harry Potter", "price": 20, "review": "hogehoge"}`) type Book struct { Title string Price int Review string <<< 新しく項目を追加する? } |
個人的にはすごくめんどくさいなと思って、構造体の定義なしでJSONデータを扱えないか調べてみました。
解決方法
以下の方法で、解決できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package main import ( "encoding/json" "fmt" ) func main() { b := []byte(`{"title": "Harry Potter", "price": 20}`) // jsonObjを用意 var bookObj map[string]interface{} if err := json.Unmarshal(b, &bookObj); err != nil { fmt.Println(err) } fmt.Println(bookObj) // keyでアクセス fmt.Println(bookObj["title"], bookObj["price"]) // Interface型で取れるのでstring型に変換 fmt.Println(bookObj["title"].(string), bookObj["price"].(float64)) } |
bookObjを用意して、InterfaceのType assertions機能を使ってデータをGoで扱える形に変換しました。
MapにKey-Value形式でデータを保存すれば、Struct構造体なしでデータを取り扱うことができます。
1 2 3 4 5 |
# 実行 $ go run main.go map[price:20 title:Harry Potter] Harry Potter 20 Harry Potter 20 |
参考になれば嬉しいです。
それでは、また!
コメントを残す
コメントを投稿するにはログインしてください。