0


SpringBoot (二) --- 返回Json数据

SpringBoot(二) — 返回Json数据

文章目录

什么是JSON

​ JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互

相当于全球通用语—英语,中国56个民族不同地区的通用语言-普通话

json的基本语法格式如下:

  • json是一种纯字符数据,不属于编程语言
  • json的语法与js中object的语法几乎一致
  • json数据中的键值对可以使用编程语言中所谓的关键字
  • json的数据可以用花括号{}或中括号[]包裹,对应js中的object和array,示例{"name":"admin","age":18}或者["SpringBoot",3.1415,"json"]
  • json数据以键值对形式存在,多个键值对之间用逗号,隔开,但数据结束后,不允许出现没有意义的逗号,键值对的键和值之间用冒号:连接,键值对的部分,必须用双引号"包裹,单引号都不行;键值对的部分,不允许出现函数functionundefinedNaN,但是可以有null

​ 在我们的项目开发中,接口与接口之间,前后端之间的数据传输都是使用的JSON格式

@RestController

​ 上文我们有提到

@RestController = @controller + @ResponseBody

,而

@ResponseBody

注解的作用就是将返回的数据转换为JSON格式。因此在SpringBoot中 使用

@RestController

注解即可将返回的数据结构转换成 JSON 格式。我们还是点进(Ctrl+左键)

@RestController

看看:

@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Mappingpublic@interfaceRequestMapping{Stringname()default"";//指定请求的实际地址@AliasFor("path")String[]value()default{};@AliasFor("value")String[]path()default{};//指定请求的method类型, GET、POST、PUT、DELETE等RequestMethod[]method()default{};//指定request中必须包含某些参数值是,才让该方法处理。String[]params()default{};//指定request中必须包含某些指定的header值,才能让该方法处理请求。String[]headers()default{};//指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;String[]consumes()default{};//指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;String[]produces()default{};}

如此,我们学到了更多

@RestController

的参数。

我们点开 pom.xml 中的 spring-boot-starter-web 依赖,可以找到spring-boot-starter-json依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>2.7.9</version><scope>compile</scope></dependency>

继续点开 spring-boot-starter-json 依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.5</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jdk8</artifactId><version>2.13.5</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.13.5</version><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-parameter-names</artifactId><version>2.13.5</version><scope>compile</scope></dependency>

我们发现出现了许多

jackson

,至此我们知道了Spring Boot 中默认使用的 JSON 解析框架是 Jackson。

不同数据类型返回的JSON

在我们平时的项目开发中,常用的数据结构有 类对象、List对象、Map对象。

创建People实体类

新建entity包与Controller同级,entity我们用来存放实体类。

image-20230324110258370

导入lombok依赖:

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>1.18.20</optional></dependency>

然后在File --> Settings --> Plugins,搜索 lombok 下载相关插件。

在entity中编写我们的实体类:

importlombok.AllArgsConstructor;importlombok.Data;@Data// 为属性添加get,set方法@AllArgsConstructor// 提供一个全参构造器,此时不在默认含有无参构造器publicclassPeople{privateStringName;privateInteger age;privateString gender;}

点击左下角

structure

,可以看到,使用了@Data 和@AllArgsConstructor,lombok依赖已经自动帮我们建立好了get,set等方法。

image-20230324112144690

创建JsonController类

分别返回People对象,List,Map<String,Object>。

importcom.pan.entity.People;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RestControllerpublicclassJsonController{@RequestMapping("/People")publicPeoplegetPeople(){returnnewPeople("tom",18,"男");}@RequestMapping("/list")publicList<People>getPeopleList(){List<People>PeopleList=newArrayList<>();PeoplePeople1=newPeople("jack",20,"男");PeoplePeople2=newPeople("lucy",23,"女");PeopleList.add(People1);PeopleList.add(People2);returnPeopleList;}@RequestMapping("/map")publicMap<String,Object>getMap(){Map<String,Object> map =newHashMap<>(3);PeoplePeople=newPeople("jan",25,"女");
        map.put("人物信息",People);
        map.put("家庭住址","北京二环路");
        map.put("代表作品","《北京的天》");
        map.put("书籍订阅",4153);return map;}}

返回结果展示

在浏览器中输入:localhost:8080/people,返回 JSON 如下:

{"age":18,"gender":"男","name":"tom"}

在浏览器中输入:localhost:8080/list,返回 JSON 如下:

[{"age":20,"gender":"男","name":"jack"},{"age":23,"gender":"女","name":"lucy"}]

在浏览器中输入:localhost:8080/map,返回 JSON 如下:

{"人物信息":{"age":25,"gender":"女","name":"jan"},
"代表作品":"《北京的天》",
"家庭住址":"北京二环路",
"书籍订阅":4153}

我们可以看到默认的 Jackson 框架将这三个常用的数据结构成功转成 JSON 格式。

补充一点

如何将String类型转换成json格式呢

我们知道@Controller如果遇到字符串会去寻找view的路径映射,而@RestController如果遇到字符串就会直接返回字符串。上面我们知道@RestController可以把数据结构转换成JSON类型。如果我们想把String返回成JSON,就需要小小的变形一下

引入依赖:

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.9</version></dependency>

重新编写我们的HelloController:

importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.JSONObject;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassHelloController{@RequestMapping("/hello")publicJSONObjectHello(){String str ="{'result': 'success','msg': '登陆成功'}";JSONObject jsonObject =  JSON.parseObject(str);return jsonObject.getClass().getName();}}

返回结果:

{"result":"success","msg":"登陆成功"}

Jackson 中对 null 的处理

在处理数据的过程中,我们难免会遇到一些 null 值。当我们转 JSON 时,不希望这些 null 出现,比如我们期望所有的 null 在转 JSON 时都变成““””这种空字符串

与controller包同级目录下我们创建一个config包用来存放我们的配置文件,并创建一个类JacksonConfig

image-20230324143032984

JacksonConfig内容:

importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.fasterxml.jackson.databind.SerializerProvider;importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importorg.springframework.http.converter.json.Jackson2ObjectMapperBuilder;importjava.io.IOException;@ConfigurationpublicclassJacksonConfig{@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)publicObjectMapperjacksonObjectMapper(Jackson2ObjectMapperBuilder builder){ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(newJsonSerializer<Object>(){@Overridepublicvoidserialize(Object o,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throwsIOException{
                jsonGenerator.writeString("");// 主要修改的地方,你哪怕填写 哦豁 null也会替换成 哦豁}});return objectMapper;}}

这里面

builder

可能会爆红,但是并不影响编译与运行,这是IDEA工具本身造成的。

添加完配置文件后,我们修改一下map的内容:

@RequestMapping("/map")publicMap<String,Object>getMap(){Map<String,Object> map =newHashMap<>(3);PeoplePeople=newPeople("jan",25,null);
        map.put("人物信息",People);
        map.put("家庭住址",null);
        map.put("代表作品","《北京的天》");
        map.put("书籍订阅",null);return map;}

比较输出结果:

添加配置类之前:

{"人物信息":{"age":25,"gender":null,"name":"jan"},
"代表作品":"《北京的天》",
"家庭住址":null,
"书籍订阅":null}

添加配置类之后:

{"人物信息":{"age":25,"gender":"","name":"jan"},
"代表作品":"《北京的天》",
"家庭住址":"",
"书籍订阅":""}

效果达成!

封装一个通用类

在项目开发中,我们不仅需要封装数据,还需要在返回的JSON数据中添加一些其他信息,比如返回状态码

code

,返回信息

msg

等,这些信息有助于调用者进行一些简单的逻辑判断。因此,我们需要封装一个统一的JSON返回数据结构。

因为封装的JSON数据类型的不确定,所以我们在定义统一的JSON结构时,需要利用泛型。统一的 JSON 结构中属性包括数据、状态码、提示信息即可,构造方法可以根据实际业务需求做相应的添加。一般来说,应该有默认的返回结构,也应该有用户指定的返回结构。

可以新建包

common

用来存放一些公共类:

R类中代码如下:

importlombok.Data;@DatapublicclassR<T>{/** 编码:1成功,0和其它数字为失败*/privateInteger code;/** 信息返回*/privateString msg;/** 信息返回数据*/privateT data;publicstatic<T>R<T>success(T object){R<T> r =newR<T>();
        r.data = object;
        r.code =1;
        r.msg =CommonConst.SUCCESS_RESULT;return r;}publicstatic<T>R<T>error(String msg){R r =newR();
        r.msg = msg;
        r.code =0;return r;}}

此外,还可以在

common

包中提前定义好返回常量:

image-20230324150905905

CommonConst类中代码如下:

publicclassCommonConst{publicstaticfinalString SUCCESS_RESULT ="获取信息成功";publicstaticfinalString ERROR_RESULT ="获取信息成功";// 需要什么信息添加什么}

这样我们也可以给R类中的msg返回

 r.msg = CommonConst.SUCCESS_RESULT;

修改JsonController的返回值类型

因为 我们的通用类

R

使用了泛型,所以所有的返回值类型都可以使用该统一结构。在具体的场景将泛型替换成具体的数据类型,非常方便,也便于维护。修改后的JsonController代码如下:

importcom.pan.common.R;importcom.pan.entity.People;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RestControllerpublicclassJsonController{@RequestMapping("/people")publicR<People>getPeople(){People people =newPeople("tom",18,"男");returnR.success(people);}@RequestMapping("/list")publicR<List<People>>getPeopleList(){List<People>PeopleList=newArrayList<>();PeoplePeople1=newPeople("jack",20,"男");PeoplePeople2=newPeople("lucy",23,"女");PeopleList.add(People1);PeopleList.add(People2);returnR.success(PeopleList);}@RequestMapping("/map")publicR<Map<String,Object>>getMap(){Map<String,Object> map =newHashMap<>();PeoplePeople=newPeople("jan",25,"女");
        map.put("人物信息",People);
        map.put("家庭住址","北京二环路");
        map.put("代表作品","《北京的天》");
        map.put("书籍订阅",4153);returnR.success(map);}}

我们重新在浏览器中输入:localhost:8080/people,返回 JSON 如下:

{"code":1,"msg":"操作成功","data":{"age":18,"gender":"男","name":"tom"}}

我们重新在浏览器中输入:localhost:8080/list,返回 JSON 如下:

{"code":1,"msg":"操作成功","data":[{"age":20,"gender":"男","name":"jack"},{"age":23,"gender":"女","name":"lucy"}]}

我们重新在浏览器中输入:localhost:8080/map,返回 JSON 如下:

{"code":1,"msg":"操作成功","data":{"人物信息":{"age":25,"gender":"女","name":"jan"},"代表作品":"《北京的天》","家庭住址":"北京二环路","书籍订阅":4153}}

补充

1.@PathVariable注解的用法和作用

@PathVariable注解的作用是 映射 URL 绑定的占位符,通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx”) 绑定到操作方法的入参中。一般与@RequestMapping(method = RequestMethod.GET)一起使用,例如我们给我们的JsonController增加一个方法:

@RequestMapping(value ="/people/{name}",method =RequestMethod.GET)//或者直接用GetMapping注解,甚至method=RequestMethod.GET可以删掉publicR<People>getMapOne(@PathVariable("name")String name){Map<String,Object> map =newHashMap<>(3);PeoplePeople=newPeople("jan",25,"女");
        map.put("name",People);
        map.put("家庭住址","北京二环路");
        map.put("代表作品","《北京的天》");
        map.put("书籍订阅",4153);returnR.success((People) map.get(name));}

我们重新在浏览器中输入:localhost:8080/people/name,返回 JSON 如下:

{"code":1,"msg":"操作成功","data":{"age":25,"gender":"女","name":"jan"}}

通过在浏览器输入

name

,直接得到map中键名

name

的值

2.自定义输出格式—Json的几个注解

@JsonIgnore: 可用来忽略不想输出某个属性的标签;

importlombok.AllArgsConstructor;importlombok.Data;@Data// 为属性添加get,set方法@AllArgsConstructor// 提供一个全参构造器,此时不在默认含有无参构造器publicclassPeople{privateStringName;privateInteger age;@JsonIgnoreprivateString gender;}

我们重新在浏览器中输入:localhost:8080/people,返回 JSON 如下:

{"code":1,"msg":"操作成功","data":{"age":18,"name":"tom"}}    // gender属性不在输出

@JsonFormat:此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如:

publicclass time{@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)privateDate date;}

**@JsonProperty:**可以指定某个属性和json映射的名称。例如我们有个json字符串为{“user_name”:”aaa”},而java中命名要遵循驼峰规则,则为userName,这时通过@JsonProperty 注解来指定两者的映射规则即可

publicclassSomeEntity{@JsonProperty("user_name")privateString userName;}

更多的注解可以查看这个包:

image-20230324163904571

g":“操作成功”,“data”:{“age”:18,“name”:“tom”}} // gender属性不在输出


**@JsonFormat:**此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如:

```java
public class time{

    @JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)
    private Date date;

}

**@JsonProperty:**可以指定某个属性和json映射的名称。例如我们有个json字符串为{“user_name”:”aaa”},而java中命名要遵循驼峰规则,则为userName,这时通过@JsonProperty 注解来指定两者的映射规则即可

publicclassSomeEntity{@JsonProperty("user_name")privateString userName;}

更多的注解可以查看这个包:

[外链图片转存中…(img-h0N86b8W-1679647709346)]

标签: json spring boot java

本文转载自: https://blog.csdn.net/qq_54103767/article/details/129754242
版权归原作者 吧啦吧啦! 所有, 如有侵权,请联系我们删除。

“SpringBoot (二) --- 返回Json数据”的评论:

还没有评论