【Go言語】jsonデータをstreamで扱うEncoder、Decoder型を試してみる
goのjsonパッケージには、jsonデータをstreamで扱うEncoder、Decoder型があります。
今回はこのEncoder、Decoderについて紹介します。
Encoderの定義
Encoderの構造体は以下のように定義されています
// An Encoder writes JSON values to an output stream.
type Encoder struct {
w io.Writer
err error
escapeHTML bool
indentBuf *bytes.Buffer
indentPrefix string
indentValue string
}
Encoderを作成するには NewEncoder 関数にio.Writerインターフェース型を渡します。
これによりstreamでの処理が可能になります。
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w, escapeHTML: true}
}
Encoderの使い方
io.Writerを受け付けるのでstreamでファイルに書き出せます。
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
)
func main() {
// jsonにencodeするデータ構造を定義します
m := map[string]interface{}{
"name": "hoge",
"age": 30,
"html": "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>吾輩は猫である</title></head><body><p>吾輩わがはいは猫である。名前はまだ無い。</p><p>どこで生れたかとんと見当けんとうがつかぬ。</p></body></html>",
}
// *File型はio.Writerインターフェース型を満たしています
w, err := os.OpenFile("encode.json", os.O_CREATE|os.O_WRONLY, 0664)
if err != nil {
fmt.Println(err)
return
}
defer w.Close()
e := json.NewEncoder(w)
// html文字をエスケープします
e.SetEscapeHTML(true)
// インデントを指定します
// 第一引数の prefixは行の先頭で文字を追加します
// 第二引数はインデント文字を指定します。
e.SetIndent("", strings.Repeat(" ", 4))
// jsonをencodeしてファイルにstreamで書き出します
if err := e.Encode(m); err != nil {
fmt.Println(err)
return
}
}
実行するとencode.jsonが作成されます。
htmlがエスケープされ、インデントが半角スペース4つになっているのがわかります。
$ cat encode.json
{
"age": 30,
"html": "\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003ctitle\u003e吾輩は猫である\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003cp\u003e吾輩わがはいは猫である。名前はまだ無い。\u003c/p\u003e\u003cp\u003eどこで生れたかとんと見当けんとうがつかぬ。\u003c/p\u003e\u003c/body\u003e\u003c/html\u003e",
"name": "hoge"
}
Decoderの定義
Decoderの構造体は以下のように定義されています。
// A Decoder reads and decodes JSON values from an input stream.
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scanp int // start of unread data in buf
scanned int64 // amount of data already scanned
scan scanner
err error
tokenState int
tokenStack []int
}
Decoderを作成するには NewDecoder 関数にio.Readerインターフェース型を渡します。
これによりstreamでの処理が可能になります。
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
Decoderの使い方
io.Readerを受け付けるのでapiのレスポンスをそのままstreamで扱えます。
今回はサンプルAPIのレスポンスを構造体にマッピングしてみます。
package main
import (
"encoding/json"
"fmt"
"net/http"
)
// マッピング用の構造体を用意
type Coffees []struct {
Title string `json:"title"`
Description string `json:"description"`
Ingredients []string `json:"ingredients"`
ID int `json:"id"`
}
func main() {
// サンプルAPIにアクセス
resp, err := http.Get("https://api.sampleapis.com/coffee/hot")
if err != nil {
fmt.Println(err)
return
}
var d Coffees
// io.ReadCloserを満たすresp.Bodyを渡して、構造体にDecode
if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%#v\n", d)
}
実行するとこのように構造体にjsonデータがマッピングされています。
$ go run decode.go
main.Coffees{struct { Title string "json:\"title\""; Description string "json:\"description\""; Ingredients []string "json:\"ingredients\""; ID int "json:\"id\"" }{Title:"Black", Description:"Black coffee is as simple as it gets with ground coffee beans steeped in hot water, served warm. And if you want to sound fancy, you can call black coffee by its proper name: cafe noir.", Ingredients:[]string{"Coffee"}, ID:1}, struct { Title string "json:\"title\""; Description string "json:\"description\""; Ingredients []string "json:\"ingredients\""; ID int "json:\"id\"" }{Title:"Latte", Description:"As the most popular coffee drink out there, the latte is comprised of a shot of espresso and steamed milk with just a touch of foam. It can be ordered plain or with a flavor shot of anything from vanilla to pumpkin spice.", Ingredients:[]string{"Espresso", "Steamed Milk"}, ID:2}, ・・・・
さいごに
いかがだったでしょうか。
Encode、Decodeの使い方を学ぶことで、Marshal、Unmarshalと併せて効率良くjsonを扱えるようになります。
goはjsonを扱う事が多いのでぜひ活用してみてください。
この記事を書いた人
- 創造性を最大限に発揮するとともに、インターネットに代表されるITを活用し、みんなの生活が便利で、豊かで、楽しいものになるようなサービスやコンテンツを考え、創り出し提供しています。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー