1. 序章

Javaアプリケーションは、データを送受信するための一般的な形式としてJSONを使用することがよくあります。 さらに、データを保存するためのシリアル化プロトコルとして使用されます。 JSONデータサイズが小さくなると、アプリケーションはより安価で高速になります。

このチュートリアルでは、JavaアプリケーションでJSONのサイズを縮小するさまざまな方法を見ていきます。

2. ドメインモデルとテストデータ

連絡先データを使用して、Customerのドメインモデルを作成しましょう。

public class Customer {
    private long id;
    private String firstName;
    private String lastName;
    private String street;
    private String postalCode;
    private String city;
    private String state;
    private String phoneNumber;
    private String email;

phoneNumberemailを除いて、すべてのフィールドが必須であることに注意してください。

JSONデータサイズの違いを適切にテストするには、少なくとも数百のCustomerインスタンスが必要です。 テストをよりリアルにするためには、異なるデータが必要です。 ここでは、データ生成Webサイトmockarooが役立ちます。 そこで、1,000個のJSONデータレコードを無料で、独自の形式で、本物のテストデータを使用して作成できます。

ドメインモデル用にmockarooを構成しましょう。

ここで、覚えておくべきいくつかの項目:

  • ここでフィールド名を指定しました
  • ここでは、フィールドのデータ型を選択しました
  • 50% ofモックデータの電話番号が空です
  • 30% ofメールアドレスも空です

以下のすべてのコード例では、mockarooの1,000人の顧客の同じデータを使用しています。 ファクトリメソッドCustomer.fromMockFile()を使用してそのファイルを読み取り、Customerオブジェクトに変換します。

JSON処理ライブラリとしてJacksonを使用します。

3. Jacksonのデフォルトオプションを使用したJSONデータサイズ

デフォルトのJacksonオプションを使用してJavaオブジェクトをJSONに書き込みましょう。

Customer[] customers = Customer.fromMockFile();
ObjectMapper mapper = new ObjectMapper();
byte[] feedback = mapper.writeValueAsBytes(customers); 

最初のCustomerのモックデータを見てみましょう。

{
  "id" : 1, 
  "firstName" : "Horatius", 
  "lastName" : "Strognell", 
  "street" : "4848 New Castle Point", 
  "postalCode" : "33432", 
  "city" : "Boca Raton", 
  "state" : "FL", 
  "phoneNumber" : "561-824-9105", 
  "email" : "hstrognell0@dailymail.co.uk"
}

デフォルトのJackonオプションを使用する場合、1,000人の顧客すべてを含むJSONデータバイト配列のサイズは181.0KBです

4. gzipで圧縮

テキストデータとして、JSONデータはうまく圧縮されます。 そのため、gzipがJSONデータサイズを削減する最初のオプションです。 さらに、JSONを送受信するための一般的なプロトコルであるHTTPに自動的に適用できます。

デフォルトのJacksonオプションで生成されたJSONを取得し、gzipで圧縮してみましょう。 これにより、元のサイズの25.3% ofの45.9KBになります。 。 したがって、構成を通じて gzip 圧縮を有効にできる場合は、Javaコードを変更せずに、JSONデータサイズを75%削減します。

Spring BootアプリケーションがJSONデータを他のサービスまたはフロントエンドに配信する場合、Spring Boot構成でgzip圧縮を有効にします。 YAML構文での典型的な圧縮構成を見てみましょう:

server:
  compression:
    enabled: true
    mime-types: text/html,text/plain,text/css,application/javascript,application/json
    min-response-size: 1024

まず、 enabled をtrueに設定して、一般的に圧縮を有効にしました。 次に、mime-typesのリストにapplication/ json を追加して、JSONデータ圧縮を具体的に有効にしました。 最後に、min-response-sizeを1,024バイト長に設定していることに注意してください。 これは、少量のデータを圧縮すると、元のデータよりも大きなデータが生成される可能性があるためです。

多くの場合、NGINXなどのプロキシまたはApacheHTTPサーバーなどのWebサーバーは、JSONデータを他のサービスまたはフロントエンドに配信します。 これらのツールでJSONデータ圧縮を構成することは、このチュートリアルの範囲を超えています。

gzip に関する以前のチュートリアルでは、gzipにはさまざまな圧縮レベルがあることが示されています。 コード例では、デフォルトのJava圧縮レベルでgzipを使用しています。 Spring Boot、プロキシ、またはWebサーバーは、同じJSONデータに対して異なる圧縮結果を取得する場合があります。

データを格納するためのシリアル化プロトコルとしてJSONを使用する場合は、データを自分で圧縮および解凍する必要があります。

5. JSONの短いフィールド名

短すぎず長すぎないフィールド名を使用することをお勧めします。 デモンストレーションのためにこれを省略しましょう。JSONでは1文字のフィールド名を使用しますが、Javaフィールド名は変更しません。 これにより、JSONデータのサイズは小さくなりますが、JSONの読みやすさは低下します。 また、すべてのサービスとフロントエンドの更新が必要になるため、データを保存する場合にのみ、これらの短いフィールド名を使用する可能性があります。

{
  "i" : 1,
  "f" : "Horatius",
  "l" : "Strognell",
  "s" : "4848 New Castle Point",
  "p" : "33432",
  "c" : "Boca Raton",
  "a" : "FL",
  "o" : "561-824-9105",
  "e" : "hstrognell0@dailymail.co.uk"
}

Javaフィールド名をそのままにして、JacksonでJSONフィールド名を簡単に変更できます。 @JsonPropertyアノテーションを使用します。

@JsonProperty("p")
private String postalCode;

1文字のフィールド名を使用すると、元のサイズの72.5% ofのデータになります。 さらに、gzipを使用すると、それが23.8%に圧縮されます。 これは、元のデータを単純に圧縮して得られた25.3%よりもはるかに小さくありません。 gzip 。 私たちは常に適切な費用便益関係を探す必要があります。 サイズを少し大きくして読みやすさを失うことは、ほとんどのシナリオではお勧めできません。

6. 配列へのシリアル化

フィールド名を完全に除外することで、JSONデータサイズをさらに削減する方法を見てみましょう。 これは、Customers配列をJSONに格納することで実現できます。 読みやすさも低下することに注意してください。 また、JSONデータを使用するすべてのサービスとフロントエンドを更新する必要があります。

[ 1, "Horatius", "Strognell", "4848 New Castle Point", "33432", "Boca Raton", "FL", "561-824-9105", "hstrognell0@dailymail.co.uk" ]

顧客を配列として保存すると、元のサイズの53.1 % o f、22.0% wi番目のgzip圧縮の出力になります。これはこれまでのところ最良の結果です。 それでも、22 % iは、元のデータをgzipで圧縮しただけで得られた25.3% weよりも大幅に小さくはありません。

顧客を配列としてシリアル化するには、JSONシリアル化を完全に制御する必要があります。 その他の例については、Jacksonチュートリアルを再度参照してください。

7. null値を除く

Jacksonおよびその他のJSON処理ライブラリは、JSONの読み取りまたは書き込み時にJSON null値を正しく処理しない場合があります。 たとえば、Jacksonは、Java null 値を検出すると、デフォルトでJSON null値を書き込みます。 そのため、JSONデータの空のフィールドを削除することをお勧めします。 これにより、空の値の初期化が各JSON処理ライブラリに委ねられ、JSONデータサイズが削減されます。

模擬データでは、電話番号を50 % o、メールアドレスを30% ofを空に設定しました。 これらのnull値を省略すると、JSONデータサイズが166.8kBまたは元のデータサイズの92.1% oに減少します。 次に、 gzip 圧縮により24.9%に低下します。

ここで、 null値を無視することと、前のセクションの短いフィールド名を組み合わせると、元のサイズの68.3% oと23.4% wのgzipという大幅な節約が得られます。

ジャクソンnull値フィールドの省略は、クラスごとまたはすべてのクラスに対してグローバルに構成できます。

8. 新しいドメインクラス

配列にシリアル化することで、これまでで最小のJSONデータサイズを達成しました。 これをさらに減らす1つの方法は、フィールド数が少ない新しいドメインモデルです。 しかし、なぜそれを行うのでしょうか?

名前と住所の2つの列を持つテーブルとしてすべての顧客を表示するJSONデータのフロントエンドを想像してみましょう。 このフロントエンド専用のJSONデータを書いてみましょう。

{
  "id" : 1,
  "name" : "Horatius Strognell",
  "address" : "4848 New Castle Point, Boca Raton FL 33432"
}

名前フィールドをnameに連結し、アドレスフィールドをaddressに連結したことに注目してください。 また、emailphoneNumberは省略しました。

これにより、はるかに小さいJSONデータが生成されます。 また、フロントエンドがCustomerフィールドを連結するのを防ぎます。 ただし、欠点として、このはバックエンドをフロントエンドに緊密に結合します。

このフロントエンド用の新しいドメインクラスCustomerSlimを作成しましょう。

public class CustomerSlim {
    private long id;
    private String name;
    private String address;

テストデータをこの新しいCustomerSlimドメインクラスに変換すると、元のサイズの46.1% oに縮小されます。 これは、デフォルトのジャクソン設定を使用します。 gzip を使用すると、15.1%になります。 この最後の結果は、以前の最良の結果である22.0%をすでに大幅に上回っています。

次に、1文字のフィールド名も使用すると、元のサイズの40.7 % oになり、gzipではさらに14.7%になります。 この結果は、ジャクソンのデフォルト設定で到達した15.1%を超えるわずかな増加にすぎません。

CustomerSlim のフィールドはオプションではないため、空の値を省略してもJSONデータサイズに影響はありません。

最後の最適化は、配列のシリアル化です。 CustomerSlimをアレイにシリアル化することで、最高の結果が得られます。元のサイズの34.2% ofと14.2% wi番目のgzipです。したがって、圧縮しなくても、元のデータの3分の2近くを削除します。 。 また、圧縮により、JSONデータが元のサイズの7分の1に縮小されます。

9. 結論

この記事では、JSONデータサイズを削減する必要がある理由を最初に説明しました。 次に、このJSONデータサイズを減らすさまざまな方法を学びました。 最後に、1つのフロントエンドにカスタム化されたドメインモデルを使用してJSONデータサイズをさらに削減する方法を学びました。

完全なコードは、いつものように、GitHubから入手できます。