はじめに
goのwebフレームワークであるEchoにてデフォルトのJSONよりも高速なJSONを返したいことがあると思います。その例としてeasyjsonで作ったJSONを返そうとしたときに少し詰まりどころがあったので書き留めておきたいと思います。
まずはデフォルトから
package main
import (
"github.com/masibw/echo_json/model"
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.GET("/", getUser)
// Start server
e.Logger.Fatal(e.Start(":1323"))
}
// Handler
func getUser(c echo.Context) error {
user := model.User{Name:"John",Age:18}
return c.JSON(http.StatusOK, user)
}
という感じで
return c.JSON(http.StatusOK, user)
と返せば良いです。
easyjsonで作ったJSONを返す
詳しいパフォーマンス測定は行っていませんが こちらの記事によるとencoding/jsonよりも2倍くらいは速そうです。
echoにて既にencoding済みのJSONを返すには
func(c echo.Context) error {
encodedJSON := []byte{} // Encoded JSON from external source
return c.JSONBlob(http.StatusOK, encodedJSON)
}
という感じで渡してあげれば良いです。ということでencodedJSONのところにeasyjsonで作ったJSONを渡しましょう。
ディレクトリ構成はこんな感じで作業します。
.
├── go.mod
├── go.sum
├── main.go
└── model
└── model.go
package model
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
easyjsonのインストール
go get -u github.com/mailru/easyjson/...
した後にmodelが記載されているディレクトリに移動して
easyjson -all <file>.go
する必要があります。
すると
<file>_easyjson.go
というファイルが作成されるはずです。
あとはプログラム内で
encodedJSON, err := easyjson.Marshal(user)
のようにJSONへencodeすることができます。
これをechoで返す様にすれば良いです。全体像がこちら
package main
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/mailru/easyjson"
"github.com/masibw/echo_json/model"
"log"
"net/http"
)
func main() {
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.GET("/", getUser)
// Start server
e.Logger.Fatal(e.Start(":1323"))
}
// Handler
func getUser(c echo.Context) error {
user := model.User{Name: "John", Age: 18}
encodedJSON, err := easyjson.Marshal(user)
if err != nil {
log.Fatal("json marshal error")
}
return c.JSONBlob(http.StatusOK, encodedJSON)
}
つまりどころ
mainパッケージに対してコマンドが実行できない
easyjson -all <file>.go
該当Issue?
なのでmodelパッケージのように別パッケージを用意してあげましょう。
それに加えて厳密な条件は調べていませんが構造体定義以外が対象ファイルに記載されているとエラーが返ってきてしまうことがあるようです。
その場合は一旦構造体のみ別パッケージに移すなりしてeasyjsonのコマンドを実行し,自動生成されたファイルをコピーして同じパッケージにすれば動きます(構造体定義が変わるたびに実行する必要があるのでめんどくさいですが)