一、问题简诉

在一次接口以对象的形式接受JSON参数时,报错NullPointException,Debug如图,发现获取的参数为null

二、问题定位

1、定位查询字段与前端传值字段名称是否对应,查询之下相比无误;

2、对应null字段是否传值为null或空,查询对比之下传值不为空或null且有效

三、排查问题

排查之下发现当传值字段JSON Key取值为大写开头时,无法对象形式自动获取参数,当为小写开头时,则可获取。

考虑SpringBoot使用Jackson做序列化,查看文档

1
2
3
4
5
6
7
8
9
10
11
12
How Jackson ObjectMapper Matches JSON Fields to Java Fields
To read Java objects from JSON with Jackson properly, it is important to know how Jackson maps the fields of a JSON object to the fields of a Java object,
so I will explain how Jackson does that.

By default Jackson maps the fields of a JSON object to fields in a Java object by matching the names of the JSON field to the getter and setter methods in the Java object.
Jackson removes the "get" and "set" part of the names of the getter and setter methods, and converts the first character of the remaining name to lowercase.

For instance, the JSON field named brand matches the Java getter and setter methods called getBrand() and setBrand().
The JSON field named engineNumber would match the getter and setter named getEngineNumber() and setEngineNumber().

If you need to match JSON object fields to Java object fields in a different way,
you need to either use a custom serializer and deserializer, or use some of the many Jackson Annotations.

可以看出,原因是,如果字段是private属性,jackson是直接根据get、set函数的命名来决定字段的命名。

而不管是PM,还是pM,他们的set方法统一是setPm(),jackson只能按照java的规范,默认开头字母小写,所以才会出现上述问题。

四、解决方案

1、JavaBean实体类直接加上注解,告诉Jackson所有的字段都可以直接按照字段名识别

1
2
@JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY,getterVisibility= JsonAutoDetect.Visibility.NONE)
public class TemperatureData {

1.JsonAutoDetect.Visibility.ANY : 表示所有字段都可以被发现, 包括private修饰的字段, 解决大小写问题;
2.JsonAutoDetect.Visibility.NONE : 表示get方法不可见,解决字段重复问题。

2、使用fastJSON