spring-mvc默认jackson对象序列化解析问题

spring-mvc默认jackson对象序列化解析问题

Controller层方法使用@ResponseBody时,默认使用jackson解析Bean对象并返回json字符串

案例

实体类

User

public class User {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

User 1

改变get方法
getName ====> getUserName
getAge ====> getUserAge

public class User1 {

    private String name;
    private Integer age;

    public String getUserName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getUserAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

User 2

新增getUserName,getUserAge方法

public class User2 {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getUserName() {
        return name;
    }
    public Integer getUserAge() {
        return age;
    }
}

Controller层

@RestController
@RequestMapping("/springmvc-json-test")
public class BasicController {

    @GetMapping("/user")
    public User user() {
        User user = new User();
        user.setName("guoyg");
        user.setAge(666);
        return user;
    }

    @GetMapping("/user1")
    public User1 user1() {
        User1 user1 = new User1();
        user1.setName("guoyg");
        user1.setAge(666);
        return user1;
    }

    @GetMapping("/user2")
    public User2 user2() {
        User2 user2 = new User2();
        user2.setName("guoyg");
        user2.setAge(666);
        return user2;
    }
}

访问结果

/user

{
"name": "guoyg",
"age": 666
}

/user1

{
"userName": "guoyg",
"userAge": 666
}

/user2

{
"name": "guoyg",
"age": 666,
"userName": "guoyg",
"userAge": 666
}

相同属性但由于getter方法不同,导致返回json不同

原理

以User1为例

  1. jackson在解析Bean对象时,com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector#collectAll()方法会收集Bean对象的所有字段和getter,setter方法对应的隐含属性名保存到prop列表中。
    prop:[name,age,userName,userAge]
  2. 然后会移除prop列表中没有getter方法对应的字段。
    prop:[userName,userAge]
  3. 使用BeanSerializer对Bean对象进行解析,即为prop列表中的字段进行赋值。