基於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之后需要使用其他的方法來設置某個屬性是否需要(反)序列化:
通過設置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中有提到:
在類上加上以上注解,工作正常。
注:並未完美解決,似乎JsonIgnoreProperties和JsonIgnore不能共存,這樣的話如果某個類既有屏蔽get方法也有屏蔽set方法的話就不知道怎么搞了
另外 https://github.com/FasterXML/jackson-databind/issues/1805 是個比較新的相關bug 跟蹤一下。
更新,已經查到問題,由於jackson在處理collection和map時會自動USE_GETTERS_AS_SETTERS,所以會產生問題,引用自己在github的comment:
使用過程中總會有
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之后需要使用其他的方法來設置某個屬性是否需要(反)序列化:
通過設置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中有提到:
在類上加上以上注解,工作正常。
注:並未完美解決,似乎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):
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.
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):
- if (propDef.hasSetter()) {
- JavaType propertyType = propDef.getSetter().getParameterType(0);
- prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);
- } else if (propDef.hasField()) {
- JavaType propertyType = propDef.getField().getType();
- prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);
- } else if (useGettersAsSetters && propDef.hasGetter()) {
- /* May also need to consider getters
- * for Map/Collection properties; but with lowest precedence
- */
- AnnotatedMethod getter = propDef.getGetter();
- // should only consider Collections and Maps, for now?
- Class<?> rawPropertyType = getter.getRawType();
- if (Collection.class.isAssignableFrom(rawPropertyType)
- || Map.class.isAssignableFrom(rawPropertyType)) {
- prop = constructSetterlessProperty(ctxt, beanDesc, propDef);
- }
- }
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.