1.1 简介
在项目开发中,接口与接口之间,前后端之间数据的传输都使用Json 格式,在Spring Boot中,接口返回 Json格式的数据很简单,在 Controller 中使用@RestController注解即可返回 Json格式的数据,@RestController也是 Spring Boot新增的一个注解,我们点进去看一下该注解都包含了哪些东西。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { String value() default ""; }
可以看出, @RestController注解包含了原来的@Controller 和 @ResponseBody注解,使用过Spring 的朋友对@Controller 注解已经非常了解了,这里不再赘述,@ResponseBody注解是将返回的数据结构转换为Json格式。所以在默认情况下,使用了 @RestController注解即可将返回的数据结构转换成Json格式,Spring Boot中默认使用的Json解析技术框架是 jackson。我们点开pom.xml 中的 spring-boot-starter-web 依赖,可以看到一个 spring-boot-starter-json依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.0.3.RELEASE</version> <scope>compile</scope> </dependency>
Spring Boot中对依赖都做了很好的封装,可以看到很多spring-boot-starter-xxx 系列的依赖,这是 Spring Boot的特点之一,不需要人为去引入很多相关的依赖了,starter-xxx系列直接都包含了所必要的依赖,所以我们再次点进去上面这个 spring-boot-starter-json依赖,可以看到:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.6</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> <version>2.9.6</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.9.6</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-parameter-names</artifactId> <version>2.9.6</version> <scope>compile</scope> </dependency>
到此为止,我们知道了Spring Boot 中默认使用的json解析框架是jackson。下面我们看一下默认的 jackson框架对常用数据类型的转Json处理。
1.2 Spring Boot 默认对Json的处理
在实际项目中,常用的数据结构无非有类对象、List对象、Map对象,我们看一下默认的jackson 框架对这三个常用的数据结构转成 json后的格式如何。
1.2.1 创建 User实体类
为了测试,我们需要创建一个实体类,这里我们就用 User 来演示。
public class User { private Long id; private String username; private String password; /* 省略get、set和带参构造方法 */ }
1.2.2 创建Controller
类
然后我们创建一个 Controller
,分别返回User
对象、List<User>
和 Map<String, Object>
。
@RestController @RequestMapping("/json") public class JsonController { @RequestMapping("/user") public User getUser() { return new User(1, "倪升武", "123456"); } @RequestMapping("/list") public List<User> getUserList() { List<User> userList = new ArrayList<>(); User user1 = new User(1, "倪升武", "123456"); User user2 = new User(2, "达人课", "123456"); userList.add(user1); userList.add(user2); return userList; } @RequestMapping("/map") public Map<String, Object> getMap() { Map<String, Object> map = new HashMap<>(3); User user = new User(1, "倪升武", "123456"); map.put("作者信息", user); map.put("博客地址", "http://"); map.put("CSDN地址", "http://"); map.put("粉丝数量", 4153); return map; } }
1.2.3 测试不同数据类型返回的json
OK,写好了接口,分别返回了一个User 对象、一个List集合和一个Map集合,其中Map 集合中的 value存的是不同的数据类型。接下来我们依次来测试一下效果。
在浏览器中输入:localhost:8080/json/user返回 json 如下:
{"id":1,"username":"倪升武","password":"123456"}
1
在浏览器中输入:localhost:8080/json/list返回 json 如下:
[{"id":1,"username":"倪升武","password":"123456"},{"id":2,"username":"达人课","password":"123456"}]
1
在浏览器中输入:localhost:8080/json/map 返回 json 如下:
{"作者信息":{"id":1,"username":"倪升武","password":"123456"},"CSDN地址":"http://blog.csdn.net/eson_15","粉丝数量":4153,"博客地址":"http://blog.itcodai.com"}
1
可以看出,map中不管是什么数据类型,都可以转成相应的json格式,这样就非常方便。
1.2.4 jackson 中对null的处理
在实际项目中,我们难免会遇到一些 null值出现,我们转json 时,是不希望有这些 null出现的,比如我们期望所有的null在转json时都变成“”这种空字符串,那怎么做呢?在Spring Boot中,我们做一下配置即可,新建一个jackson 的配置类:
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 JacksonConfig { @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; } }
然后我们修改一下上面返回map
的接口,将几个值改成null
测试一下:
@RequestMapping("/map") public Map<String, Object> getMap() { Map<String, Object> map = new HashMap<>(3); User user = new User(1, "倪升武", null); map.put("作者信息", user); map.put("博客地址", "http://"); map.put("CSDN地址", null); map.put("粉丝数量", 4153); return map; }
重启项目,再次输入:localhost:8080/json/map,可以看到jackson已经将所有null字段转成了空字符串了。
{"作者信息":{"id":1,"username":"倪升武","password":""},"CSDN地址":"","粉丝数量":4153,"博客地址":"http://blog.itcodai.com"}
1
1.3 使用阿里巴巴FastJson的设置
1.3.1 jackson和fastJson的对比
有很多朋友习惯于使用阿里巴巴的fastJson 来做项目中 json转换的相关工作,目前我们项目中使用的就是阿里的fastJson,那么jackson 和 fastJson 有哪些区别呢?根据网上公开的资料比较得到下表。
选项 | fastJson | jackson |
---|---|---|
上手难易程度 | 容易 | 中等 |
高级特性支持 | 中等 | 丰富 |
官方文档、Example支持 | 中文 | 英文 |
处理json速度 | 略快 | 快 |
1.3.2 fastJson
依赖导入
使用fastJson
需要导入依赖,本课程使用1.2.35
版本,依赖如下:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.35</version> </dependency>
1.3.3 使用fastJson处理null
使用fastJson 时,对 null的处理和jackson有些不同,需要继承WebMvcConfigurationSupport 类,然后覆盖 configureMessageConverters方法,在方法中,我们可以选择对要实现 null转换的场景,配置好即可。如下:
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @Configuration public class fastJsonConfig extends WebMvcConfigurationSupport { /** * 使用阿里 FastJson 作为JSON MessageConverter * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures( // 保留map空的字段 SerializerFeature.WriteMapNullValue, // 将String类型的null转成"" SerializerFeature.WriteNullStringAsEmpty, // 将Number类型的null转成0 SerializerFeature.WriteNullNumberAsZero, // 将List类型的null转成[] SerializerFeature.WriteNullListAsEmpty, // 将Boolean类型的null转成false SerializerFeature.WriteNullBooleanAsFalse, // 避免循环引用 SerializerFeature.DisableCircularReferenceDetect); converter.setFastJsonConfig(config); converter.setDefaultCharset(Charset.forName("UTF-8")); List<MediaType> mediaTypeList = new ArrayList<>(); // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json" mediaTypeList.add(MediaType.APPLICATION_JSON); converter.setSupportedMediaTypes(mediaTypeList); converters.add(converter); } }
1.4 封装统一返回的数据结构
以上是 Spring Boot 返回json 的几个代表的例子,但是在实际项目中,除了要封装数据之外,我们往往需要在返回的json中添加一些其他信息,比如返回一些状态码code ,返回一些 msg给调用者,这样调用者可以根据 code或者 msg做一些逻辑判断。所以在实际项目中,我们需要封装一个统一的json返回结构存储返回信息。
1.4.1 定义统一的 json结构
由于封装的json数据的类型不确定,所以在定义统一的json 结构时,我们需要用到泛型。统一的json结构中属性包括数据、状态码、提示信息即可,构造方法可以根据实际业务需求做相应的添加即可,一般来说,应该有默认的返回结构,也应该有用户指定的返回结构。如下:
public class JsonResult<T> { private T data; private String code; private String msg; /** * 若没有数据返回,默认状态码为0,提示信息为:操作成功! */ public JsonResult() { this.code = "0"; this.msg = "操作成功!"; } /** * 若没有数据返回,可以人为指定状态码和提示信息 * @param code * @param msg */ public JsonResult(String code, String msg) { this.code = code; this.msg = msg; } /** * 有数据返回时,状态码为0,默认提示信息为:操作成功! * @param data */ public JsonResult(T data) { this.data = data; this.code = "0"; this.msg = "操作成功!"; } /** * 有数据返回,状态码为0,人为指定提示信息 * @param data * @param msg */ public JsonResult(T data, String msg) { this.data = data; this.code = "0"; this.msg = msg; } // 省略get和set方法 }
1.4.2 修改 Controller 中的返回值类型及测试
由于 JsonResult 使用了泛型,所以所有的返回值类型都可以使用该统一结构,在具体的场景将泛型替换成具体的数据类型即可,非常方便,也便于维护。在实际项目中,还可以继续封装,比如状态码和提示信息可以定义一个枚举类型,以后我们只需要维护这个枚举类型中的数据即可(在本课程中就不展开了)。根据以上的JsonResult,我们改写一下Controller,如下:
@RestController @RequestMapping("/jsonresult") public class JsonResultController { @RequestMapping("/user") public JsonResult<User> getUser() { User user = new User(1, "倪升武", "123456"); return new JsonResult<>(user); } @RequestMapping("/list") public JsonResult<List> getUserList() { List<User> userList = new ArrayList<>(); User user1 = new User(1, "倪升武", "123456"); User user2 = new User(2, "达人课", "123456"); userList.add(user1); userList.add(user2); return new JsonResult<>(userList, "获取用户列表成功"); } @RequestMapping("/map") public JsonResult<Map> getMap() { Map<String, Object> map = new HashMap<>(3); User user = new User(1, "倪升武", null); map.put("作者信息", user); map.put("博客地址", "http://"); map.put("CSDN地址", null); map.put("粉丝数量", 4153); return new JsonResult<>(map); } }
我们重新在浏览器中输入:localhost:8080/jsonresult/user返回json如下:
{"code":"0","data":{"id":1,"password":"123456","username":"倪升武"},"msg":"操作成功!"}
1
输入:localhost:8080/jsonresult/list,返回json 如下:
{"code":"0","data":[{"id":1,"password":"123456","username":"倪升武"},{"id":2,"password":"123456","username":"达人课"}],"msg":"获取用户列表成功"}
1
输入:localhost:8080/jsonresult/map,返回json 如下:
{"code":"0","data":{"作者信息":{"id":1,"password":"","username":"倪升武"},"CSDN地址":null,"粉丝数量":4153,"博客地址":"http://blog.itcodai.com"},"msg":"操作成功!"}
1
通过封装,我们不但将数据通过json传给前端或者其他接口,还带上了状态码和提示信息,这在实际项目场景中应用非常广泛。
标签:map,jackson,Spring,Boot,json,Json,User,new,public From: https://www.cnblogs.com/Fooo/p/17296181.html