Spring / Jackson + @JsonView:JSONのフィルタリング


こんにちは

最近、彼の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; } // not included, bail out: if (i == len) { _delegate.serializeAsOmittedField(bean, jgen, prov); return; } } _delegate.serializeAsField(bean, jgen, prov); 

つまり オブジェクトフィールドをマークしたビューがViewコントローラーメソッドのスーパークラスと一致するか、スーパークラスである場合、フィールドはシリアル化されます。 それ以外の場合、スキップserializeAsOmittedFieldます( serializeAsOmittedField )。

解決策


要約すると:


これで、 passwordフィールドは結果に含まれなくなりpassword 。 RESTコントローラーでは、 @JsonViewを使用せずに実行できます。 すべてのユーザーフィールドがそこに含まれています。

ご清聴ありがとうございました! @JsonViewがSpringアプリケーションをより美しくコンパクトにすることを願っています。

Source: https://habr.com/ru/post/J307392/


All Articles