Jackson 序列化/反序列化時忽略某屬性


基於Spring MVC的RESTful接口基本都使用了Jackson這個類庫。

使用過程中總會有
1. 序列化時忽略某屬性(如Password)
2. 反序列化時忽略某屬性(如HashedPassword)

其實對應在Bean中,就是類的Setter/Getter方法。

Jackson提供了@Jsonignore這個注解,用於在(反)序列化時,忽略bean的某項屬性。在Jackson 1.9的時候,@Jsonignore的語義還有了變化,如下:

1.9之前:
在Setter方法上加@Jsonignore注解並不會影響Getter方法的調用

1.9之后:
在Setter方法上加@Jsonignore會導致整個這個屬性在序列化過程中被忽略。
https://stackoverflow.com/questions/12505141/only-using-jsonignore-during-serialization-but-not-deserialization

所以在1.9之后需要使用其他的方法來設置某個屬性是否需要(反)序列化:
Java代碼   收藏代碼
  1. @JsonProperty(access = Access.WRITE_ONLY)  


通過設置JsonProperty的access屬性來確定當前屬性是不是需要自動序列化/反序列化。

WRITE_ONLY:僅做反序列化操作。
READ_ONLY:僅做序列化操作。

現在的問題是,2.8.7版本的jackson databind (start.spring.io在引入Spring-Web-Starter時候自動引入的,版本是Spring Boot 1.5.X-RELEASE), 在使用READ_ONLY時,並沒有忽略反序列化操作,查詢了一下應該是jackson databind的一個bug:
https://github.com/FasterXML/jackson-databind/issues/95
https://github.com/FasterXML/jackson-databind/issues/935
盡管bug已經關閉,但是似乎還是有問題,這時候有以下Work around在935中有提到:

Java代碼   收藏代碼
  1. @JsonIgnoreProperties(value="some_field", allowGetters = true, allowSetters = false)  

在類上加上以上注解,工作正常。

注:並未完美解決,似乎JsonIgnoreProperties和JsonIgnore不能共存,這樣的話如果某個類既有屏蔽get方法也有屏蔽set方法的話就不知道怎么搞了
另外 https://github.com/FasterXML/jackson-databind/issues/1805 是個比較新的相關bug 跟蹤一下。

更新,已經查到問題,由於jackson在處理collection和map時會自動USE_GETTERS_AS_SETTERS,所以會產生問題,引用自己在github的comment:

引用
wwwcomy commented 4 minutes ago • edited
Facing the same problem, in issue #935, seems only simple types were handled correctly.

I looked into the code, the issue was caused by some special logic for USE_GETTERS_AS_SETTERS, in BeanDeserializerFactory Line 565 (version 2.8.10):

Java代碼   收藏代碼
  1. if (propDef.hasSetter()) {  
  2.                 JavaType propertyType = propDef.getSetter().getParameterType(0);  
  3.                 prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);  
  4.             } else if (propDef.hasField()) {  
  5.                 JavaType propertyType = propDef.getField().getType();  
  6.                 prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);  
  7.             } else if (useGettersAsSetters && propDef.hasGetter()) {  
  8.                 /* May also need to consider getters 
  9.                  * for Map/Collection properties; but with lowest precedence 
  10.                  */  
  11.                 AnnotatedMethod getter = propDef.getGetter();  
  12.                 // should only consider Collections and Maps, for now?  
  13.                 Class<?> rawPropertyType = getter.getRawType();  
  14.                 if (Collection.class.isAssignableFrom(rawPropertyType)  
  15.                         || Map.class.isAssignableFrom(rawPropertyType)) {  
  16.                     prop = constructSetterlessProperty(ctxt, beanDesc, propDef);  
  17.                 }  
  18.             }  

By default USE_GETTERS_AS_SETTERS is enabled, so, although the Collection member was defined Access as "READ_ONLY", still, it is set as a property in the builder instance.

My work around is using (for spring boot applications) spring.jackson.mapper.USE_GETTERS_AS_SETTERS=false

However, I'm not sure this behavior is a bug or not, @cowtowncoder please help to clarify.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM