Spring Boot学习笔记(一)Json数据封装与统一数据返回格式

前言

在我们日常开发过程中,接口与接口之间,前后端之间数据的传输都使用 JSON 格式。本文介绍Sping Boot中

一、JSON简介

文章开始之前,我们先简单回顾一下JSON的概念
参考自官方JSON中文说明以及JSON维基百科

(1)名称:

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)

(2)与XML对比:

JSON是一种轻量级的资料交换语言,而XML是一个完整的标记语言,这使得XML在程序判读上需要比较多的功夫。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面相较JSON更具优势,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。

(3)语法:

  1. 数据在名称/值对中:json数据是由键值对构成的, 键用引号(单双都行)引起来,也可以不使用引号
  2. 数据由逗号分隔:多个键值对由逗号分隔
  3. 花括号保存对象:使用{}定义json 格式
  4. 方括号保存数组:[ ]
  5. 值的取值类型:
    1. 数字(整数或浮点数)
    2. 字符串(在双引号中)
    3. 逻辑值(true 或 false)
    4. 数组(在方括号中) {“persons”:[{},{}]}
    5. 对象(在花括号中) {“address”:{“province”:“广东”…}}
    6. null

(4)JSON解析器:

常见的解析器:Gson(Google的JSON处理框架),fastjson(阿里巴巴的JSON处理框架),jackson(Spring Boot默认JSON处理框架)

二、Spring Boot默认对JSON的处理

(1)创建Spring Boot工程并在pom.xml加入依赖如下

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 </dependencies>

这里我们只需关注spring-boot-starter-web 依赖
在IDEA中,对着spring-boot-starter-web依赖按住CTRL+鼠标左键
在这里插入图片描述
可以看到spring-boot-starter-web封装了一个spring-boot-starter-json依赖
在这里插入图片描述
我们再点进去,可以看到jackson的各项依赖已经被封装好
在这里插入图片描述

(2)创建实体类命名为Person.java

public class Person {
    private String name;
    private Integer age;
    private Integer phoneNumber;

    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 Integer getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(Integer phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
    public Person(String name,Integer age,Integer phoneNumber){
        this.name = name;
        this.age = age;
        this.phoneNumber = phoneNumber;
    }
}

(3)创建Controller类命名为PersonController.java

import com.rex.springbootjson.entity.Person;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController

public class PersonController {
    @RequestMapping("/person")
    public Person getPerson(){
        return new Person("张三",18,123);
    }
    @RequestMapping("/list")
    public List<Person> getPersonList() {
        List<Person> personList = new ArrayList<>();
        Person user1 = new Person("李四",18,123);
        Person user2 = new Person("王五",15,321);
        personList.add(user1);
        personList.add(user2);
        return personList;
    }
    @RequestMapping("/map")
    public Map<String, Object> getPersonMap() {
        Map<String, Object> map = new HashMap<>(3);
        Person person = new Person("王五",24,321);
        map.put("成员信息", person);
        map.put("住址", null);
        map.put("学历", "本科");
        return map;
    }
}

这里我们重点关注@RestController注解
CTRL+鼠标左键点开@RestController注解,可见其封装了@Controller注解。而@RestController与@Controller的主要区别是:
1. @RestController是将json/xml返回到前端页面
2. @Controller是将HTML页面返回到前端页面

而另一个注解@ResponseBody的作用简而言之就是将对象转化为JSON格式
具体详解可以参考@ResponseBody详解
在这里插入图片描述

(4)启动Spring Boot项目

  1. 访问http://localhost:8080/person
    在这里插入图片描述
  2. 访问http://localhost:8080/list,返回List类型的JSON
    在这里插入图片描述

3.访问http://localhost:8080/map ,返回map类型的JSON
在这里插入图片描述

三、 jackson 中对null的处理

由上图,地址一栏出现了null值,实际项目开发中难免会遇到一些 null 值出现,我们转 json 时,是不希望有这些 null 出现的,比如我们期望所有的 null 在转 json 时都变成 “” 这种空字符串,此时我们需要新建一个JSON配置类

  1. 创建JsonConfig.java文件,加入如下代码
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;

@Configuration
public class JsonConfig {
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeString("");
            }
        });
        return objectMapper;
    }
}

  1. 重启Spring Boot项目,重新访问http://localhost:8080/map
    在这里插入图片描述
    可以看到null值已经被处理

四、统一数据返回格式

1.为什么要做统一数据返回格式

在以前后端分离为主流的开发环境下,前后端开发人员需要通过API交互,但为了前端人员能够快速做逻辑展示与页面交互处理,每一次RESTful请求都应该包含以下几个信息:

名称描述
状态码标识请求成功与否,如[1:成功; -1:失败]
错误码定义明确错误码,更好的应对业务异常;请求成功该值可为空
错误消息与错误码相对应,更具体的描述异常信息
resultBody通常是Bean对象对应的JSON数据,通常为了应对不同返回值类型,将其声明为泛型类型

这里总结下我们常用的状态码以及表示的含义:

code区间类型含义
1**100-199信息 服务器接收到请求,需要请求者继续执行操作
2**200-299成功 请求被成功接收并处理
3**300-399重定向 需要进一步的操作以完成请求
4**400-499客户端错误 请求包含语法错误或无法完成请求
5**500-599服务器错误 服务器在处理的时候发生错误

2.统一的JSON结构的配置

在config文件夹下创建UnifiedReturnConfig文件

package com.rex.springbootjson.config;

import com.rex.springbootjson.entity.CommonResult;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

@EnableWebMvc
@Configuration
public class UnifiedReturnConfig {

    @RestControllerAdvice("com.rex.springbootjson.Controller")
    static class CommonResultResponseAdvice implements ResponseBodyAdvice<Object> {
        @Override
        public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
            return true;
        }

        @Override
        public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
            if (body instanceof CommonResult){
                return body;
            }

            return new CommonResult<Object>(body);
        }
    }
}

在entity文件下创建实体类CommmonResult,添加如下代码

package com.rex.springbootjson.entity;



public final class CommonResult<T> {

    private int status = 1;

    private String errorCode = "";

    private String errorMsg = "";

    private T resultBody;

    public CommonResult() {
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public T getResultBody() {
        return resultBody;
    }

    public void setResultBody(T resultBody) {
        this.resultBody = resultBody;
    }

    public CommonResult(T resultBody) {
        this.resultBody = resultBody;
    }
}

3.在controller类下PersonController添加如下代码

 @RequestMapping("/CommonResult")
    public CommonResult<Object> getUserList() {
        List<Person> personList2 = new ArrayList<>();
        Person user1 = new Person("李四",18,123);
        Person user2 = new Person("王五",15,321);
        personList2.add(user1);
        personList2.add(user2);
        return new CommonResult<Object>(personList2);
    }

好的,我们的统一返回格式已经大功告成,接下来测试。

3.测试接口

访问http://localhost:8080/CommonResult
返回结果如下

{"status":1,
"errorCode":"",
"errorMsg":"",
"resultBody":[{"name":"李四","age":18,"phoneNumber":123},{"name":"王五","age":15,"phoneNumber":321}]}

下面我们随便访问一个不存在的接口,如http://localhost:8080/aaa,(这里用浏览器可能直接Whitelabel Error Page)用接口测试工具可以返回如下结果

{"timestamp":1603540190184,
"status":404,"error":
"Not Found",
"message":"","path":"/aaa"}

总结

本文仅是对Spring Boot的json处理及统一返回做一个实例,是本人在学习过程中的总结与实践。

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值