spring默认使用的是jackson处理json的序列化和反序列化,有一些细节和小坑,基于spring4和jackson2.8做一些说明
@JsonIgnore
@JsonIgnore是jackson的注解,jackson1版本和2版本没有区别,通常当做标志注解(没有要赋值的属性),常用于属性上
json序列化反序列化都会忽略该属性
@JsonIgnoreProperties
@JsonIgnoreProperties是Jackson的注解,jackson1版本和2版本有区别,1版本只能放在类上,2版本类、方法、属性都可以,为了保持习惯,一般还是都放在类上
- ignoreUnknown属性,默认为false,此时反序列化json字符串时,有bean中没有的字段,就会抛出异常
- value属性,默认为空,可以放入要忽略的字段,作用和@JsonIgnore一样,可以统一管理忽略字段
- demo:
@JsonIgnoreProperties(ignoreUnknown = true, value = {"id","name"})
@JsonProperty
@ JsonProperty是Jackson的注解,jackson1版本和2版本区别很大,常用于属性上
- value属性,1、2版本一样,默认为"",代表该属性序列化和反序列化时的key值
- required属性,2.0版本新增属性,默认false,2.6版本之后只能用于@JsonCreator中。例子中required=true,当反序列化时,json串中没有x或y,就会报错。不实用,一般不用该属性
/**
* Note that as of 2.6, this property is only used for Creator
* Properties, to ensure existence of property value in JSON:
* for other properties (ones injected using a setter or mutable
* field), no validation is performed. Support for those cases
* may be added in future.
* State of this property is exposed via introspection, and its
* value is typically used by Schema generators, such as one for
* JSON Schema.
*/
public class MyClass {
@JsonCreator
public MyClass(@JsonProperty(value = "x", required = true) Integer x, @JsonProperty(value = "value_y", required = true) Integer y) {
this.x = x;
this.y = y;
}
private Integer x;
private Integer y;
}
- defaultValue属性,2.5版本新增属性,jackson2.8该属性依然没有作用
/**
* It is possible that in future this annotation could be used for value
* defaulting, and especially for default values of Creator properties,
* since they support {@link #required()} in 2.6 and above.
* /
- access属性,2.6版本新增属性,默认Access.AUTO(不控制序列化反序列化权限),此外还有
READ_ONLY
(仅可以序列化)、WRITE_ONLY
(仅可以反序列化)、READ_WRITE
(序列化反序列化都可以),一共四种。分别控制序列化反序列化的权限,所以JsonProperty注解使用该属性可以取代JsonIgnore注解,控制的更加精细。
PS:access的源码注释中说明JsonIgnore优先于access属性,但是我在测试的时候,对同一个属性同时使用这两个注解,则两个注解都失效了,不知道为什么?????
/**源码中的注释
* Note that while this annotation modifies access to annotated property,
* its effects may be further overridden by {@link JsonIgnore} property:
* if both annotations are present on an accessors, {@link JsonIgnore}
* has precedence over this property.
*/
@Test
public void testSerial() throws JsonProcessingException {
JsonBean jsonBean = new JsonBean();
jsonBean.setAaa("aaa");
jsonBean.setBbb("bbb");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(jsonBean));
}
@Test
public void testDeserial() throws IOException {
String json = "{\"aaa\":\"aaa\",\"bbb\":\"bbb\"}";
ObjectMapper mapper = new ObjectMapper();
JsonBean jsonBean = mapper.readValue(json, JsonBean.class);
System.out.println(jsonBean);
}
@Data //lombok插件注解,自动生成set、get、toString等方法
class JsonBean {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@JsonIgnore
private String aaa;
private String bbb;
}
对序列化反序列化的控制总结:
- JsonIgnoreProperties放到类上,集中管理属性参不参与json转换
- JsonIgnore放到类的属性上,控制该属性参不参与json转换,文档中说放到set方法或者get方法上表现不一样,但是我测试的时候,放到get、set、属性上表现的都一样,都是不参加json的序列化反序列化
- JsonProperty放到类的属性上,通过access可以分开控制该属性参不参与json的序列化或反序列化
Spring中对jackson的配置
Spring中使用@ResponseBody和@RequestBody都会在converter中用到jackson,所以需要配置converter中使用的jackson
<mvc:annotation-driven>
<mvc:message-converters>
1:<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion" value="NON_NULL"/>
</bean>
</property>
<property name="targetMethod" value="configure"/>
<property name="arguments">
<list>
<value>FAIL_ON_UNKNOWN_PROPERTIES</value>
<value>false</value>
</list>
</property>
</bean>
</property>
</bean>
2:<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
- 该bean用来处理@ResponseBody和@RequestBody的json转换,通过Spring的MethodInvokingFactoryBean来生成ObjectMapper实例,该bean的配置相当于:
new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
设置DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false
之后,bean中就无需使用@JsonIgnoreProperties(ignoreUnknown = true)
- 该bean用来处理使用@ResponseBody的Controller返回String,默认情况使用的时iso8859-1的编码,需要改成UTF-8
网友评论