使用过程中总会有
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 = 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中有提到:
@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):
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.