JSON-框架的具体使用
非 SpringBoot 项目
Jackson
Jackson
是另一个流行的JSON
序列化和反序列化库,具有以下特点
- 速度快:
Jackson
采用了高效的JSON
解析算法和字节码生成技术,使得其序列化和反序列化速度非常快。 - 支持全类型序列化:
Jackson
能够序列化所有类型的对象,包括复杂类型和自定义类型。 - 功能强大:
Jackson
提供了很多高级特性,如JSON 映射、注解和 JSON 树模型
等,使得其在企业级应用中得到广泛应用。
-
依赖
<!-- 测试 JSON 框架时项目所有依赖 --> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.13.0</version> </dependency> </dependencies>
-
使用示例
package org.example.demo; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; public class JacksonExample { public static void main(String[] args) throws JsonProcessingException { // 将 Java 对象转换为 JSON 字符串 User user = new User("Tom", 18); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); System.out.println(json); // {"name":"Tom","age":18} // 将 JSON 字符串转换为 Java 对象 String jsonStr = "{\"name\":\"Tom\",\"age\":18}"; User user2 = mapper.readValue(jsonStr, User.class); System.out.println(user2.getName() + " " + user2.getAge()); // Tom 18 } @Data @NoArgsConstructor @AllArgsConstructor static class User { private String name; private int age; } }
Gson
Gson
是JSON
序列化和反序列化库。Gson
也是一个非常流行的JSON
序列化和反序列化库,具有以下特点
-
简单易用:
Gson
的使用非常简单,只需要在项目中引入gson.jar
,即可开始使用。 -
高度灵活性:
Gson
可以很方便地处理各种类型的对象,包括Java 8
的新特性,如LocalDate
和LocalDateTime
-
扩展性强:
Gson
提供了很多扩展点,可以方便地进行自定义扩展。 -
依赖
<!-- 测试 JSON 框架时项目所有依赖 --> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.9</version> </dependency> </dependencies>
-
使用示例
package org.example.demo; import com.google.gson.Gson; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; public class GsonExample { public static void main(String[] args) { // 将 Java 对象转换为 JSON 字符串 User user = new User("Tom", 18); Gson gson = new Gson(); String json = gson.toJson(user); System.out.println(json); // {"name":"Tom","age":18} // 将 JSON 字符串转换为 Java 对象 String jsonStr = "{\"name\":\"Tom\",\"age\":18}"; User user2 = gson.fromJson(jsonStr, User.class); System.out.println(user2.getName() + " " + user2.getAge()); // Tom 18 } @Data @NoArgsConstructor @AllArgsConstructor static class User { private String name; private int age; } }
Fastjson
Fastjson
是阿里巴巴开源的JSON
序列化和反序列化库,由于其高效性和稳定性,成为目前使用最广泛的JSON
序列化和反序列化库之一。以下是Fastjson
的主要特点
-
高性能:
Fastjson
采用了许多优化措施,如字节码生成和对象池,使得其反序列化速度非常快,序列化速度也很快。 -
支持全类型序列化:
Fastjson
能够序列化所有类型的对象,包括复杂类型和自定义类型。 -
兼容性好:
Fastjson
支持JSON
标准规范,并且与其他JSON
库兼容。 -
使用方便:
Fastjson
的使用非常简单,几乎不需要配置,只需要在项目中引入fastjson.jar
,即可开始使用。 -
依赖
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> </dependencies>
-
用法
package org.example.demo; import com.alibaba.fastjson.JSON; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; public class FastjsonExample { public static void main(String[] args) { // 将 Java 对象转换为 JSON 字符串 User user = new User("Tom", 18); String json = JSON.toJSONString(user); System.out.println(json); // {"age":18,"name":"Tom"} // 将 JSON 字符串转换为 Java 对象 String jsonStr = "{\"age\":18,\"name\":\"Tom\"}"; User user2 = JSON.parseObject(jsonStr, User.class); System.out.println(user2.getName() + " " + user2.getAge()); // Tom 18 } @Data @NoArgsConstructor @AllArgsConstructor static class User { private String name; private int age; } }
SpringBoot项目中使用
Jackson
-
介绍
在
Spring Boot
中,JSON
序列化和反序列化默认使用Jackson
库,因此不需要额外配置Jackson
的依赖。但如果想使用Fastjson
或Gson
库,可以通过以下方式配置Maven
依赖 -
依赖导入未发生变化
-
Jackson: 不需要添加,因为当添加
spring-boot-starter-web
的依赖时内部已经添加了jackson
Gson
-
因为使用
spring-boot-starter-web
内部已经有jackson
,为了使用gson
,所以排除jackson
的依赖<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.9</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
-
yml
# 可以配置的一些参数 spring: gson: # 用于指定日期格式化的格式字符串,将 Java 对象中的日期类型属性转换成对应的字符串形式。示例配置 yyyy-MM-dd HH:mm:ss 表示使用标准的日期格式将日期类型属性转换成字符串形式。如果不配置该属性,则使用 Gson 默认的日期格式化方式。 date-format: yyyy-MM-dd HH:mm:ss # disable-html-escaping:用于指定是否禁用 HTML 转义,当序列化 HTML 内容时,开启该选项可以防止 XSS 攻击。该属性默认值为 false,即默认启用 HTML 转义。 disable-html-escaping: true # disable-inner-class-serialization:用于指定是否禁用序列化内部类,默认值为 false,即序列化内部类。 disable-inner-class-serialization: true # enable-complex-map-key-serialization:用于指定是否启用复杂类型的 Map 键的序列化,默认值为 false,即禁用复杂类型的 Map 键的序列化。 enable-complex-map-key-serialization: true # exclude-fields-without-expose-annotation:用于指定是否排除未标注 @Expose 注解的字段,默认值为 false,即不排除未标注 @Expose 注解的字段。 exclude-fields-without-expose-annotation: true # field-naming-policy:用于指定字段命名策略,默认值为 IDENTITY,即使用 Java 对象中的字段名称作为 Gson 中的字段名称。其他可选值包括 LOWER_CASE_WITH_UNDERSCORES、UPPER_CAMEL_CASE 和 UPPER_CAMEL_CASE_WITH_SPACES 等。 field-naming-policy: LOWER_CASE_WITH_UNDERSCORES # serialize-nulls:用于指定是否序列化 null 值,默认值为 false,即不序列化 null 值。 serialize-nulls: true
-
也可以通过
GsonBuilder
实现,两种方式选择一种@Configuration public class GsonConfig { @Bean public GsonBuilder gsonBuilder() { GsonBuilder builder = new GsonBuilder(); builder.setDateFormat("yyyy-MM-dd HH:mm:ss"); return builder; } }
配置前 配置后( builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
)
Fastjson
-
使用程度较低
-
排除依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
-
注意点
需要注意的是,使用
Fastjson 或 Gson
时,要保证它们的依赖包的版本与Spring Boot
的依赖包版本兼容,避免出现不必要的冲突和错误。在
SpringMVC
框架 中,jackson
和gson
已经自动配置好了,只需要添加相应的依赖,而Fastjson
则需要开发者手动配置HttpMessageConverter
,直接启动会出现如下错误Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
-
解决方法
package com.example.jsondemo.config; 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.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebMvcConfig implements WebMvcConfigurer { /** * 使用 Fastjson 作为 HTTP 消息转换器 */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); converter.setFastJsonConfig(getFastJsonConfig()); converters.add(converter); } /** * 配置 Fastjson */ private FastJsonConfig getFastJsonConfig() { FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteDateUseDateFormat); // 也可以直接在 yml 文件中配置 config.setDateFormat("yyyy-MM-dd HH:mm:ss"); return config; } }
配置前 配置后 -
yml
spring: fastjson: date-format: yyyy-MM-dd HH:mm:ss
-
-
测试
@SpringBootTest class JsonDemoApplicationTests { @Test void contextLoads() { User user = new User(); user.setUid("1001"); user.setUname("coder-itl"); user.setAddress("http://coderitl.github.io"); user.setCreateTime(new Date(System.currentTimeMillis())); String toJSONString = JSON.toJSONString(user); System.out.println(toJSONString); // 反序列化 } }
-
输出
测试序列化
-
序列化和反序列化
-
序列化: 对象转换为
JSON
-
反序列化:
JSON
转换为对象 -
如何实现序列化和反序列化这个过程的?
-
由转换器:
HttpMessageConverter
实现在
Spring
框架中,HttpMessageConverter
是一个用于在消息传递时将消息从一种格式转换为另一种格式的接口。它的主要作用是帮助在不同的客户端和服务之间传递消息,并确保消息在传递过程中能够正确地序列化和反序列化。Spring
框架中提供了多个预定义的HttpMessageConverter
实现,可以根据不同的需求选择使用。常用的消息格式包括JSON、XML、二进制
等。配置
HttpMessageConverter
可以通过在Spring
应用程序上下文中注册HttpMessageConverter
类型的Bean
来实现。具体语法如下@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MappingJackson2HttpMessageConverter()); } }
上面的示例配置了一个
MappingJackson2HttpMessageConverter
对象,用于将Java
对象转换为JSON
格式的消息。在这个例子中,我们使用了Spring 的 Java
配置方式,并实现了WebMvcConfigurer
接口中的configureMessageConverters()
方法来注册我们自己的MessageConverter
实现。需要注意的是,当我们自定义
MessageConverter
时,必须添加到converters
列表的前面,以确保它是在默认的转换器之前被调用的。此外,我们也可以通过重写extendMessageConverters()
方法来添加自定义的MessageConverter
,这个方法会在默认的转换器之后调用。
-