2014-10-08 29 views
2

我急需幫助。我目前正在對Content API中的某個資源進行一些安全性限制,其中我需要:包括屬性,截斷屬性(如果它們是String.class),或者基於SecurityContext從序列化對象中移除屬性。自定義BeanPropertyFilter - 僅序列化字符串的一部分

我使用傑克遜作爲我的json序列化程序,並選擇使用BeanPropertyFilter來檢查每個屬性是否應該序列化。

現在,刪除和包含選項非常簡單,無論是否序列化bean。

但是truncate選項有點惡化。所以這裏是關於房產的序列化迄今爲止所做的。

@Override 
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception { 
    switch (determineFilterAction(writer)) { 
     case INCLUDE_UNMODIFIED: 
      writer.serializeAsField(bean, jgen, provider); 
      break; 
     case INCLUDE_TRUNCATED: 
      Object value = writer.get(bean); 
      if (!(value instanceof String)) { 
       throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported"); 
      } 
      JsonSerializer oldSerialzer= writer.getSerializer(); 
      writer.assignSerializer(new TruncateStringJsonSerializer()); 
      writer.serializeAsField(bean, jgen, provider); 
      writer.assignSerializer(oldSerialzer); 
      break; 
     case REMOVE: 
      // do nothing 
      break; 
    } 
} 

問題是,有一個在BeanPropertyWriter.assignSerializer()方法保護,不會讓我在一個新的自定義序列轉換爲一個屬性。

是否有任何方法掛鉤並修改bean值?或者我將不得不重寫Factories和BeanPropertyWriter以覆蓋assignSerializer()方法(以避免序列化器守護)?

我不能用特殊的編寫器註釋我的屬性,因爲序列化對象不知道有關SecurityContext的任何內容,所以沒有辦法將securityContext注入到自定義序列化器中。

有沒有什麼辦法可以使這個截斷選項發生(而不會太過分)?

在此先感謝。

//最好的問候,馬丁。

UPDATE

基於StaxMan的回答,我已經更新,看起來像這樣的方法,它似乎工作。至少我所有的測試都能正確運行。將在開發應用程序服務器上進一步測試。

@Override 
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider provider, BeanPropertyWriter writer) throws Exception { 
    switch (determineFilterAction(writer)) { 
     case INCLUDE_UNMODIFIED: 
      writer.serializeAsField(bean, jgen, provider); 
      break; 
     case INCLUDE_TRUNCATED: 
      Object value = writer.get(bean); 
      if (!(value instanceof String)) { 
       throw new UnsupportedOperationException("Annotation indicates truncate on " + writer.toString() + " which is not a string, but a " + value.getClass().getSimpleName() + " and is unsupported"); 
      } 
      String valueString = (String) value; 
      jgen.writeFieldName(writer.getName()); 
      jgen.writeString(StringUtils.abbreviate(valueString, MAX_LENGTH)); 
      break; 
     case REMOVE: 
      // do nothing 
      break; 
    } 
} 
+0

如果我可以覆蓋默認的BeanPropertyWriter,即傑克遜用我自己的方法初始化並註冊它,它可以覆蓋防止我切換出序列化程序的警衛。但我無法找到任何人如何做到這一點在網絡上。 (至少不是沒有實施自己的工廠提供商和自己的工廠)。我不太喜歡。 – 2014-10-08 09:30:08

回答

2

沒有,甚至沒有嘗試調用assignSerializer:這是在多線程環境中的壞主意 - 有僅僅是串行器的單一實例,即使你可以稱呼它,它會只是在兩個序列化同時完成的情況下,會造成一個奇怪的例外。

但也許你應該考慮從不同的方向來解決這個問題:既然你已經找到了String的值,那麼爲什麼不直接用JsonGenerator寫截斷值呢? 或者,如果你願意的話,委託給寫作的東西;但既然你叫它,它不需要是JsonSerializer或任何東西。

+0

感謝您的回覆。這幫助,並且工作。它有一點點醜陋,只是在做一個手動寫入,我寧願讓傑克遜安裝程序處理它。 很好的瞭解assignSerializer,我認爲傑克遜可以處理這個,當它可以處理與@JsonSerialize(使用= SomeCustomSerializer.class)切換序列化程序。甚至有一個註釋在源代碼中,評論天氣或不在將來的版本中刪除警衛。 :) – 2014-10-09 06:44:35

+0

是的,它並不總是清楚什麼可以,特別是應該做什麼。也許這種方法應該有一個警告說明。加上基本的'JsonSerializer'和'JsonDeserializer'應該強調這樣一個事實,即實例需要是線程安全的,因爲實例被共享用於併發使用。 – StaxMan 2014-10-09 17:27:14