22
11

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 5 years have passed since last update.

and factoryAdvent Calendar 2018

Day 9

【grpc-gateway】0, false, nullなどの値をJSON出力対象にする

Last updated at Posted at 2018-12-08

はじめに

例えばgRPCのメソッド、メッセージが以下だとして

syntax = "proto3";

import "google/protobuf/empty.proto";
import "google/api/annotations.proto";

package proto;

service TestService {
    rpc Test (google.protobuf.Empty) returns (TestMessage) {
        option (google.api.http) = {
            get: "/test"
        };
    }
}

message TestMessage {
    int32 a = 1;
    bool b = 2;
    string c = 3;
    repeated string d = 4;
}

サーバからクライアントに送るメッセージが(極端ですが)以下のような内容だったとします。

TestMessage {
  a: 0,
  b: false,
  c: "",
  d: nil
}

grpc-gateway経由で上記のメッセージを受け取った場合、空のJSONがレスポンスとして返ってきてしまいます。しかし、本当は以下のようなレスポンスが返ってきて欲しいです。

{ "a": 0, "b": false, "c": "", "d": [] }

ということでこのような設定にする方法を調べましたが、日本語の記事が見つからなかったのでQiitaに載せておきます。

やりかた

grpc-gatewayに、ゼロ値は省略せずにJSONの項目に含めてくれるオプションがありますので、それを指定してgrpc-gatewayのサーバを起動すれば万事解決です。

opts := []runtime.ServeMuxOption{
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}),
}

mux := runtime.NewServeMux(opts...)

原因

そもそも、なぜJSONのレスポンスに0や空文字が含まれていないのかという話ですが、Protocol Bufferから作成されたGo用の構造体にomitemptpyが指定されているためです。

type TestMessage struct {
	A                    int32    `protobuf:"varint,1,opt,name=a,proto3" json:"a,omitempty"`
	B                    bool     `protobuf:"varint,2,opt,name=b,proto3" json:"b,omitempty"`
	C                    string   `protobuf:"bytes,3,opt,name=c,proto3" json:"c,omitempty"`
	D                    []string `protobuf:"bytes,4,rep,name=d,proto3" json:"d,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

しかも、このomitemptyはハードコードで指定されているのでprotocでコンパイルすときには必ず指定されてしまいます…

上記のような理由から、構造体に指定されているomitemptyを無視してゼロ値を出力するオプションがgrpc-gateway側で作成されたようです。ありがとうphilipithomasさん!

参考リンク

golang protobuf remove omitempty tag from generated json tags -Stack Overflow
Support emitting default values in JSON #233

22
11
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
22
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?