jsonをエンコードしたりデコードしたりする

プログラミング学習帳 プログラミング

json形式のデータを扱う機会はとても多い。フロントエンドとバックエンド間でAPI通信をしようとした時、必要になってくる処理の1つが、json形式のデータを受け取った後、編集できる形式に変換したり、json形式のデータに戻したりというものである。

エンコードやデコードって何?

エンコードは、データを別の形式に変換すること。主にフロントエンドで使われる。フロントエンドにて”json.stringify()でエンコードした”ということは、すなわち”あるjavascriptの値やオブジェクトをjson形式に変換した”ということを指す。json.stringify()を使うことで、json形式のオブジェクトとして使えるようになる。

const requestBody: any = message;
let requestOptions: RequestInit = {
  body: JSON.stringify(requestBody),
  method: method,
  headers: headers,
  credentials: "include",}

一方でデコードは、エンコードされたものを元の形式に戻すこと。主にバックエンドで使われる。jsonで言えば、エンコードされたものを元の形式に戻ることがデコード。フロントエンドではjson.parseを使う。Goではjson.Marshalを使って構造体をJSON形式に変換する。JSON形式に変換してネットワーク越しに送信したいときに使う。逆にjson形式で受け取った値を指定した構造体に変換するのがjson.Unmarshal。ネットワーク越しにデータを受け取った時に使う。

func (app *application) writeJSON(w http.ResponseWriter, status int, data interface{}, headers ...http.Header) error {
 out, err := json.Marshal(data)
 if err != nil {
	return err
}

つぎにjson.NewDecoder。これもjson.Unmarshalと同様に、json形式で受け取ったデータを構造体に変換するもの。json.NewDecoderでは、Decodeメソッドを用いて、データ読み込みの終わりにio.EOFエラーを返す処理が必要になる。大規模なデータを読み込む場合は特にNewDecoderの方が有用。

func (app *application) readJSON(w http.ResponseWriter, r *http.Request, data interface{}) error {
 maxBytes := 1024 * 1024 //1 mega byte
 r.Body = http.MaxBytesReader(w, r.Body, int64(maxBytes))
 dec := json.NewDecoder(r.Body) //decoder
 dec.DisallowUnknownFields()

json.Unmarshalとjson.NewDecoderの違い

さて、json.Unmarshalとjson.NewDecoderは性質が似ている。両方ともjson形式で受け取ったデータを構造体に変換する。違いは、json.Unmarshalはバイト配列のJSONデータを一度に読み込んでGoのデータ構造に変換するのに対し、json.NewDecoderはストリーム形式で提供されるJSONデータを逐次的に読み込んでGoのデータ構造に変換するために使用される。

ストリーム形式で提供されるJSONデータとは、大きなJSONデータが一度に全て提供されるのではなく、小さな塊に分割され、逐次的に提供される形式のことを指す。ストリーム形式で提供されるJSONデータは、ファイルやネットワークなどの入力ソースから一部ずつ読み込まれるため、一度にすべてのデータをメモリに読み込む必要がない。これは、大規模なJSONデータを処理する場合に特に有用。例えば、TwitterのストリーミングAPIを使用してリアルタイムでツイートを受信する場合、大量のJSONデータがストリーム形式で提供される。この場合、json.NewDecoderを使用することで、受信したJSONデータを逐次的に処理していくことができる。

なお、ストリーム形式で提供されるJSONデータは、開始と終了が明確でないため、逐次的に読み込みながらデータが終了したかどうかを判断する必要がある。これは、json.NewDecoderのDecodeメソッドを使用することで実現できる。Decodeメソッドは、ストリームから次のJSONオブジェクトを読み込み、それをGoのデータ構造に変換する。もしストリームの終端に到達した場合、Decodeメソッドはio.EOFエラーを返す。

io.EOFは、Go言語の標準ライブラリで定義されているエラーの一つで”End Of File”の略称。これは、入力ソースから読み込み操作を行った際に、ソースの終端に到達したことを示すエラー。例えば、ファイルを読み込んでいる際に、ファイルの最後まで読み込んだ場合、io.EOFが返される。同様に、ネットワーク通信を行っている場合にも、データの受信が終了した場合にio.EOFが返される。io.EOFは、エラーとして扱われますが、単なる終端に到達したことを示すため、エラーとして処理される必要はない。json.NewDecoderDecodeメソッドを使用する際には、ストリームから次のJSONオブジェクトを読み込んだ際にio.EOFが返された場合、それがストリームの終端であることを示しているため、特別な処理を行うことができる。

コメント

タイトルとURLをコピーしました