3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

echoでより高速なJSONを返す

Last updated at Posted at 2020-09-12

はじめに

goのwebフレームワークであるEchoにてデフォルトのJSONよりも高速なJSONを返したいことがあると思います。その例としてeasyjsonで作ったJSONを返そうとしたときに少し詰まりどころがあったので書き留めておきたいと思います。

まずはデフォルトから

main.go
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
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で返す様にすれば良いです。全体像がこちら

main.go
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のコマンドを実行し,自動生成されたファイルをコピーして同じパッケージにすれば動きます(構造体定義が変わるたびに実行する必要があるのでめんどくさいですが)

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?