📝

JavaScriptのTextEncoderを使ってJSONのバイトサイズを調べる

に公開

AppSyncでとってきたGraphQLのレスポンスのサイズを調べたくなり、JavascriptにTextEncorderというものがあることを知ったので、備忘もかねてご紹介します!

なぜバイトサイズを測りたくなったか

GraphQL + DynamoDB を使っていると、AppSyncやDynamoDBのレスポンスサイズ制限(1MB)に引っかかることがあります。

今回は、200件程度あるはずのデータが100件しか取れていなかったため、レスポンスのサイズを図ろうとしていました。

しかし、単に data.length とか JSON.stringify(data).length で文字数やアイテム数を見ても、正確なバイト数ではありません

実際に "あ" のような日本語の1文字は、UTF-8では3バイト使います。
でも .length は1を返します。これでは、制限にかかるかどうかの判断に使えません。

最初に試した方法とその落とし穴

まずは単純に JSON.stringify(...).length を使ってみました。

const str = JSON.stringify(data);
console.log(str.length); // ← これは文字数

ですが、これは 「文字数」 であり、「バイトサイズ」ではありません。
UTF-8のような可変長文字コードでは、1文字 = 1バイトとは限りません。

TextEncoderにたどり着いた

いろいろ調べてたどり着いたのが、TextEncoder というAPIでした。

これは、文字列をUTF-8でエンコードして、Uint8Array(バイナリ配列)を返してくれる便利なWeb APIです。

const encoder = new TextEncoder();
const json = JSON.stringify(data);
const bytes = encoder.encode(json);
console.log(bytes.length); // ← 正確なバイトサイズ!

これで「見た目は小さく見えるけど、実際は大きかった」データも正確に測れます。

実際のコード例:大量データのサイズを測ってみる

例えば、AppSyncでページネーションしたいときに、「1ページ何件まで大丈夫?」と確認するためのコードがこちらです。

const encoder = new TextEncoder();
const sizes = items.map(i => encoder.encode(JSON.stringify(i)).length);

const total = sizes.reduce((a, b) => a + b, 0);
const avg = total / sizes.length;

console.log({
  件数: sizes.length,
  平均サイズ: avg,
  合計サイズ: total,
  最大サイズ: Math.max(...sizes),
});

これで、トータルのレスポンスサイズと1アイテムの中での最大サイズが分かります。

ほかにも使える場面

TextEncoderは、他にもこんな場面で使えるのではないかと思います。

  • LocalStorage の容量上限(約5MB)に収まるかチェックしたいとき
  • メール本文の長さをバイトで見積もりたいとき
  • CSVファイル出力時のサイズ確認
  • ネットワーク送信前にサイズを調べて分割処理する場合 など

注意点

  • UTF-8専用:TextEncoder は UTF-8 固定。他の文字コード(Shift_JISなど)は扱えません。
  • Node.jsでも使用可能:v11以降であれば、global.TextEncoder として利用できます。
  • 古いブラウザ(IEなど)では非対応ですが、モダン環境ならまず問題なしです。

まとめ

  • JSON.stringify(...).length は文字数、正確なバイト数ではない
  • バイトサイズを測りたいなら、TextEncoderが簡単で正確
  • AppSyncやDynamoDB、LocalStorageなど、サイズ制限のあるAPIでの事前チェックにとても役立つ!

ぶっちゃけテキストファイルとして保存すればよかったか…?と思いましたが、覚えておいて損はないAPIかと思います!

DELTAテックブログ

Discussion