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アプリケーションをより美しくコンパクトにすることを願っています。



All Articles