自学内容网 自学内容网

SpringBoot 属性大写无法绑定

一、场景分析

假设有如下一个对象,它的三个属性全部大写。

package com.study.member.entity;
import lombok.Data;
@Data
public class Member {
    private String NAME;
    private Integer AGE;
    private String PHONE;
}

在使用 SpringMVC 进行接口调用的时候,会发现入参 member 的属性并没有正确绑定。

package com.study.member.controller;

import com.study.member.entity.Member;
import com.study.common.base.R;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("member")
public class MemberController {

    @PostMapping("/register")
    public R<Void> register(@RequestBody Member member) {
        System.out.println(member);
        return R.success();
    }
}
-------------------------------------------------
POST http://localhost:8080/member/register
Content-Type: application/json

{
  "NAME": "会员",
  "AGE": 11,
  "PHONE": "12345678"
}
输出:
Member(NAME=null, AGE=null, PHONE=null)

 像这种属性全部大写的情况,也是我们平常可能会遇到的场景。

比如,这个接口是开放给第三方回调的,第三方回调的 JSON 报文 的对象属性并不一定都是严格的首字母小写驼峰格式。有时候跨语言系统的相互调用,这种情况就更常见了。

二、解决方案

在 Spring Boot 中,可以通过以下几种方式指定 JSON 填充的属性名称

1、使用 @JsonProperty 注解

在实体类的属性上使用 @JsonProperty 注解来指定在 JSON 中的属性名称。

package com.study.member.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class Member {
    @JsonProperty(value="NAME")
    private String NAME;
    @JsonProperty(value="AGE")
    private Integer AGE;
    @JsonProperty(value="PHONE")
    private String PHONE;
}
-------------------------------------------------
POST http://localhost:8080/member/register
Content-Type: application/json

{
  "NAME": "会员",
  "AGE": 11,
  "PHONE": "12345678"
}
输出:
Member(NAME=会员, AGE=11, PHONE=12345678)

当然,对象属性你也可以按首字母小写驼峰格式命名,jackson 也能正确绑定。

package com.study.member.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class Member {

    @JsonProperty(value="NAME")
    private String name;

    @JsonProperty(value="AGE")
    private Integer age;

    @JsonProperty(value="PHONE")
    private String phone;
}
-------------------------------------------------
POST http://localhost:8080/member/register
Content-Type: application/json

{
  "NAME": "会员",
  "AGE": 11,
  "PHONE": "12345678"
}
输出:
Member(name=会员, age=11, phone=12345678)

 不过,使用这个注解的话,在 JSON 数据反序列化时,使用的也还是 @JsonProperty 注解配置的名称:

package com.study.member.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class Member {

    @JsonProperty(value="NAME")
    private String name;

    @JsonProperty(value="AGE")
    private Integer age;

    @JsonProperty(value="PHONE")
    private String phone;
}
-------------------------------------------------
package com.study.member.controller;

import com.study.member.entity.Member;
import com.study.common.base.R;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("member")
public class MemberController {

    @GetMapping("/findByName")
    public R<Member> findByName(String name) {
        Member member = new Member();
        member.setName(name);
        member.setAge(21);
        member.setPhone("456");
        return R.success(member);
    }
}
-------------------------------------------------
POST http://localhost:8080/member/findByName?name=小林
Content-Type: application/json

输出:
{
  "code": 0,
  "msg": "success",
  "data": {
    "NAME": "小林",
    "AGE": 21,
    "PHONE": "456"
  }
}

 那如果希望对象JSON在反序列化的时候,不改变属性名称,那怎么办呢?使用 @JsonAlias 注解。

2、使用 @JsonAlias 注解

@JsonAlias 可以为属性提供一个或多个别名,在 JSON 处理时可以使用这些别名来填充属性。 

package com.study.member.entity;

import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Data;

@Data
public class Member {

    @JsonAlias({"NAME", "NICK_NAME"})
    private String name;

    @JsonAlias(value="AGE")
    private Integer age;

    @JsonAlias(value="PHONE")
    private String phone;
}
-------------------------------------------------
@RestController
@RequestMapping("member")
public class MemberController {

    @PostMapping("/register")
    public R<Void> register(@RequestBody Member member) {
        System.out.println(member);
        return R.success();
    }
}
-------------------------------------------------
###
POST http://localhost:8080/member/register
Content-Type: application/json

{
  "NAME": "会员",
  "NICK_NAME": "一心",
  "AGE": 11,
  "PHONE": "12345678"
}
输出:
Member(name=一心, age=11, phone=12345678)

可以看到,有多个别名填充同一个属性时,按顺序填充,最后是 NICK_NAME 被填充进去。

这种方式,对象JSON在被反序列化时,并不改变属性名称。

@RestController
@RequestMapping("member")
public class MemberController {

    @GetMapping("/findByName")
    public R<Member> findByName(String name) {
        Member member = new Member();
        member.setName(name);
        member.setAge(21);
        member.setPhone("456");
        return R.success(member);
    }
}
-------------------------------------------------
GET http://localhost:5911/member/findByName?name=小王
Content-Type: application/json

输出:
{
  "code": 0,
  "msg": "success",
  "data": {
    "name": "小王",
    "age": 21,
    "phone": "456"
  }
}


原文地址:https://blog.csdn.net/matrixlzp/article/details/142577824

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!