一、遇到问题
我们在使用@RestController+@RequestBody 这种注解方式做web交互时,经常会遇到如下三种场景:
①请求字段映射不到值
②返回字段大小写与预期的不一致(字段首字母大写)
③某个属性字段序列化需要忽略(不演示)
①②问题Demo演示如下
请求需要的实体 |
应答需要的实体 |
Controller处理 |
Postman请求和报文内容:
|
二、分析原因
这种情况如果字段本身可以对应的上,首先就是要考虑是不是json解析出了问题, 因为springboot默认使用jackson来格式化web交互的json串 ,所以此时就要从jackson下手,查询jackson资料。
三、查询资料
Jackson简介:
Jackson是一个简单基于Java应用库,可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。
Jackson的常用注解:
JackSon提供了一些的注解,可以用在类上或者是在字段上。通常是数据绑定的时候使用。
1、@JsonIgnoreProperties(ignoreUnknown = true) : 用来忽略序列化实体类时不需要的属性(jackson默认序列化实体类的所有属性,不存在则报错。)
2、@JsonIgnoreProperties({ “userAge”, “userWeight” }) : 指定忽略字段
3、@JsonIgnore: 标在注解上,将忽略此字段
4、@JsonInclude(param) JsonInclude.Include.NON_EMPTY:属性为空或者null都不参与序列化 JsonInclude.Include.NON_NULL:属性为null不参与序列化
5、@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”) : 序列化时使用指定时间跪着(默认转化成时间戳)
6、@JsonProperty("fieldName") : 标在字段上,指定序列化后的字段名
7、@JsonAutoDetect 该注解用来 改变默认的自动检测,标记在类上
jackson默认大小写敏感,且首字母转小写 用来指定字段、方法的可见性规则@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
附加知识点:
@JsonAutoDetect部分源码:
|
Jackson自动检测的规则 对象的属性被初次确定的过程称为自动检测:所有的成员方法和字段被查找。 1.1.“Getter”方法:所有public,带返回值,符合“getXxx”(“isXxx”,如果返回boolean,被称为“isgetter”) 命名约定的成员方法被推测存在名字为“xxx”的属性(属性名按照bean命名约定推测,即开头大写字母转成小写)。 1.2.field属性:所有public成员字段被推测要显示的属性,使用字段名字来序列化。 在相同的逻辑属性中同时存在getter和field的情况下。getter方法优先被使用(field被忽略)。 属性集被解析使用这个过程被认为是基本属性集。但自动检测过程本身可以进行不同的配置,并有多个注释和配置设置,可以进一步改变属性的真实有效集序列化。
|
四、解决方法:
1、这三个场景中①和②其实是一样的原因
方法一:用第6个注解 @JsonProperty("fieldName")标识每一个字段
日志 |
方法二:用第7个注解 @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
实体 |
日志 |
postman |
2、问题③某个属性字段序列化需要忽略
可以根据实际情况Jackson的常用注解(1、2、3、4)处理。
五、回看问题
综上看,实体映射结果不正确的最主要原因是:变量的命名不规范,导致getter不准确,所以我们开发还是要严格遵守代码规范。