JSONIgnoreアノテーションのポイントは、特定のフィールドがnullであるか省略されている場合に、特定のフィールドを無視するようにDispatcherServlet(またはSpringのコンポーネントが応答のレンダリングを処理する)に指示することです。
これにより、特定の場合にクライアントに公開するデータに関してある程度の柔軟性が得られます。
JSONIgnoreの欠点:
ただし、最近自分のプロジェクトで遭遇したこのアノテーションを使用することには、いくつかの欠点があります。これは主にPUTメソッドに適用され、コントローラーがデータをシリアル化するオブジェクトが、そのデータをデータベースに格納するために使用されるオブジェクトと同じである場合に適用されます。
PUTメソッドは、サーバー上に新しいコレクションを作成するか、サーバー上のコレクションを更新する新しいコレクションに置き換えることを意味します。
サーバー上のコレクションを置き換える例:
サーバーにPUTリクエストを作成していて、RequestBodyにシリアル化されたMovieエンティティが含まれているが、このMovieエンティティにはアクターが省略されているため含まれていないとします。後で、ユーザーが映画の説明のスペルミスを編集および修正できるようにする新機能を実装し、PUTを使用して映画エンティティをサーバーに送り返し、データベースを更新します。
ただし、オブジェクトにJSONIgnoreを追加してからかなり時間が経過しているため、特定のフィールドがオプションであることを忘れたとしましょう。クライアント側では、俳優のコレクションを含めるのを忘れてしまい、ユーザーが誤って映画Aを俳優B、C、Dで上書きし、映画Aでは俳優がまったく上書きされなくなりました。
JSONIgnoreがオプトインするのはなぜですか?
特定のフィールドを必須にすることをオプトアウトすることを強制する背後にある意図は、これらのタイプのデータ整合性の問題を回避するためです。JSONIgnoreを使用していない世界では、データを自分で明示的に設定しない限り、データが部分的なデータに置き換えられないことを保証します。JSONIgnoreを使用すると、これらのセーフガードを削除できます。
そうは言っても、JSONIgnoreは非常に価値があり、クライアントに送信されるペイロードのサイズを減らすために、まったく同じ方法でJSONIgnoreを使用します。ただし、私はこの戦略を再考し始めており、代わりに、データベースとの対話に使用するものとは別のレイヤーでPOJOクラスを使用してフロントエンドにデータを送信する戦略を選択しています。
より良いセットアップの可能性?:
この特定の問題を扱った私の経験から、理想的なセットアップは、セッターの代わりにエンティティオブジェクトにコンストラクタインジェクションを使用することです。エンティティが部分的に埋められないように、インスタンス化時にすべてのパラメータを渡す必要があります。それらを部分的に埋めようとすると、コンパイラーは、後悔する可能性のあることを実行できなくなります。
特定のデータを省略したいクライアント側にデータを送信する場合は、別の切断されたエンティティPOJOを使用するか、org.jsonのJSONObjectを使用できます。
クライアントからサーバーにデータを送信する場合、フロントエンドが部分的なデータを取得するかどうかはあまり気にしないため、フロントエンドエンティティオブジェクトはモデルデータベースレイヤーから部分的または完全にデータを受信します。ただし、データストアにデータを保存するときは、最初にデータストアから既に保存されているオブジェクトをフェッチし、そのプロパティを更新してから、データストアに保存し直します。つまり、アクターが欠落している場合でも、データストアから更新するオブジェクトには既にアクターがプロパティに割り当てられているため、問題にはなりません。したがって、明示的に置き換える予定のフィールドのみを置き換えます。
このセットアップには、より多くのメンテナンスオーバーヘッドと複雑さがありますが、強力な利点が得られます。Javaコンパイラが後を絶ちません。データストア内のデータを危険にさらす可能性のあるコードで、あなたや不幸な同僚でさえも何もできなくなります。モデルレイヤーでその場でエンティティを作成しようとすると、コンストラクターを使用する必要があり、すべてのデータを提供する必要があります。すべてのデータがなく、オブジェクトをインスタンス化できない場合は、空の値を渡すか(赤いフラグを通知する必要があります)、最初にデータストアからそのデータをフェッチする必要があります。