
こんにちは
最近、彼のSpringトレーニングプロジェクトで、Java Enterprise(Topjava)はコントローラーに応じてJSONのユーザーオブジェクトのシリアル化をカスタマイズするタスクに直面しました:コントローラーのREST APIの場合、UI上のディスプレイコントローラーではなく、ハッシュされたパスワード(
user.passwordフィールド)を返す必要がありました。 TO(
データ転送オブジェクト )だけでなく、Spring 4.2 + / Jackson 2.6でも
JacksonのSerialization Viewsを使用することで、額の問題を解決できます。 しかし、記事には落とし穴があり、不注意な読者にとっては、ビューは期待どおりに機能しません。
その結果、どのように機能するかを理解するために、ジャクソンの実装を少し掘り下げなければなりませんでした。 これについて簡単に:
MapperFeature.DEFAULT_VIEW_INCLUSION
この記事には少し言及があります。
Spring MVCのデフォルト設定では、MapperFeature.DEFAULT_VIEW_INCLUSIONはfalseに設定されています。
これは、デフォルトでは、
@JsonViewアノテーションでマークされていないフィールド
@JsonView除外されることを意味します。 しかし、
MapperFeatureコードを見ると、
MapperFeatureことがわかります。
... * Default value is enabled, meaning that non-annotated * properties are included in all views if there is no * {@link com.fasterxml.jackson.annotation.JsonView} annotation. * * Feature is enabled by default. */ DEFAULT_VIEW_INCLUSION(true),
つまり、すべてが正反対です。マークされていないものはすべてオンになります。 また、UIに必要な[ユーザー]フィールドのみをマークした場合:
public class User ... @JsonView(View.UI.class) protected String email; @JsonView(View.UI.class) protected boolean enabled = true; protected String password;
@JsonViewタグ付き
@JsonViewメソッドを呼び出します
@JsonView(View.UI.class) @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public User get(@PathVariable("id") int id) { return ...; }
その結果には、マークされたユーザーフィールド(
email, enabled, .. )と、残りすべて(
password )の両方が含まれます。
FilteredBeanPropertyWriter
なぜなら UIコントローラから
passwordフィールドを1つだけ除外したいのですが、それだけをマークするのが論理的です。 コード
jackson-databind-2.8.0を見てください。コントローラーのリクエストとその結果のフィールドに
@JsonView注釈が付けられている
@JsonView 、Jacksonは
FilteredBeanPropertyWriter.serializeAsField介してシリアル化します
final Class<?> activeView = prov.getActiveView(); if (activeView != null) { int i = 0, len = _views.length; for (; i < len; ++i) { if (_views[i].isAssignableFrom(activeView)) break; }
つまり オブジェクトフィールドをマークしたビューがViewコントローラーメソッドのスーパークラスと一致するか、スーパークラスである場合、フィールドはシリアル化されます。 それ以外の場合、スキップ
serializeAsOmittedFieldます(
serializeAsOmittedField )。
解決策
要約すると:
- シリアル化コンテキストごとに1つのビューを作成します
public class View { public static class REST {} public static class UI {} }
- 存在する必要のあるビュー(REST)によってUIで除外されるユーザーフィールドにマークを付けます。
public class User ... protected String email; protected boolean enabled = true; @JsonView(View.REST.class) protected String password;
- 適切なコンテキストでUIコントローラーメソッドに注釈を付けます
@JsonView(View.UI.class) @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public User get(@PathVariable("id") int id) { return ...; }
これで、
passwordフィールドは結果に含まれなくなり
password 。 RESTコントローラーでは、
@JsonViewを使用せずに実行できます。 すべてのユーザーフィールドがそこに含まれています。
ご清聴ありがとうございました!
@JsonViewがSpringアプリケーションをより美しくコンパクトにすることを願っています。