第1章 注意事项
JDK里面默认是不带对JSON的支持的, 所以要使用JSON需要引入其他第三方依赖
目前市面上常见的JSON框架有: fastjson(阿里出品) gson(谷歌出品) jackson(推荐使用)
第2章 JSON格式
1.1 普通JSON
格式: 键使用双引号引起来, 值如果是字符串也需要使用双引号引起来, 如果是数字则可以直接写
{ "name”:”parkour”, “age”:28 }
JSON里面嵌套JSON
{ "name”:”parkour”, “age”:28, “hobby”: {“java”:”like”,“basketball”:”unlike”} }
1.2 JSON数组
格式
[ { "name”:”parkour”, “age”:28 },{ "name”:”xiaoqinyun”, “age”:18 } ]
1.3 前端中JSON和JavaScript对象的区分
很多人搞不清楚 JSON 和 JavaScript 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
let obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
let json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
1.4 前端中JSON和JavaScript对象互转
let obj = JSON.parse('{"a": "Hello", "b": "World"}'); // JSON字符串转换为JavaScript 对象
//结果是 {a: 'Hello', b: 'World'}
let json = JSON.stringify({a: 'Hello', b: 'World'}); // JavaScript 对象转换为JSON字符串
//结果是 '{"a": "Hello", "b": "World"}'
第3章jackson框架的使用(推荐使用)
为什么推荐使用:
1.fastjson经常被爆出有漏洞使用jackson更安全
2.Spring Boot 默认的json解析器就是Jackson
3.1 导入依赖
注意: 不要导错导入jackson-databind了
因为 jackson-databind不支持java8的日期时间格式如: localdatetime, 只有jackson-datatype-jsr310才支持
<!--导入jackson依赖(支持java8日期格式的)-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.4</version>
</dependency>
3.2 jackson中对日期的特殊处理
private static ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 注入java时间模块, 指定日期的序列化与反序列化格式
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(javaTimeModule);
return mapper;
}
3.3 json与对象之间的相互转换
抽取JacksonUtil工具类
public class JacksonUtil {
/**
* 将对象转换成JSON数据
*
* @param data 对象
* @return JSON数据
*/
public static String beanToJson(Object data) {
try {
return getObjectMapper().writeValueAsString(data);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将JSON数据转换成对象
*
* @param jsonData JSON数据
* @param beanType 对象类型
* @return 对象
*/
public static <T> T jsonToBean(String jsonData, Class<T> beanType) {
try {
return getObjectMapper().readValue(jsonData, beanType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将JSON数据转换成列表
*
* @param jsonData JSON数据
* @param beanType 对象类型
* @return 列表
*/
public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
try {
ObjectMapper mapper = getObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);
return mapper.readValue(jsonData, javaType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将JSON数据转换成Set集合
*
* @param jsonData JSON数据
* @param elementType 元素类型
* @return Set集合
*/
public static <E> Set<E> jsonToSet(String jsonData, Class<E> elementType) {
try {
ObjectMapper mapper = getObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructCollectionType(Set.class, elementType);
return mapper.readValue(jsonData, javaType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将JSON数据转换成Map集合
*
* @param jsonData JSON数据
* @param keyType 键类型
* @param valueType 值类型
* @return Map集合
*/
public static <K, V> Map<K, V> jsonToMap(String jsonData, Class<K> keyType, Class<V> valueType) {
try {
ObjectMapper mapper = getObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructMapType(Map.class, keyType, valueType);
return mapper.readValue(jsonData, javaType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取一个ObjectMapper对象
*
* @return 一个初始化后的ObjectMapper对象
*/
private static ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
// 注入java时间模块, 指定日期的序列化与反序列化格式
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
mapper.registerModule(javaTimeModule);
return mapper;
}
}
测试
public class JacksonDemo {
public static void main(String[] args) throws Exception {
testBeanToJson();
testJsonToBean();
testJsonToList();
testJsonToSet();
testJsonToMap();
}
/**
* 测试将bean对象转换成json
*/
public static void testBeanToJson(){
//1.准备数据
Student student1 = new Student();
student1.setId("110");
student1.setName("狗娃");
student1.setBirthday(LocalDateTime.now());
student1.setAddress(new Address("家庭地址:四川","学习地址:北京"));
Student student2 = new Student();
student2.setId("120");
student2.setName("狗剩");
student2.setBirthday(LocalDateTime.now());
student2.setAddress(new Address("家庭地址:湖南","学习地址:上海"));
List<Student> list = new ArrayList<>();
list.add(student1);
list.add(student2);
// 2.转换
String jsonStr = JacksonUtil.beanToJson(student1);
String jsonListStr = JacksonUtil.beanToJson(list);
System.out.println(jsonStr);
System.out.println(jsonListStr);
}
/**
* 测试将json转换成普通的javabean对象(非集合类对象)
*/
public static void testJsonToBean(){
//1.准备数据
String jsonStr = "{\"id\":\"110\",\"name\":\"狗娃\",\"birthday\":\"2022-10-22 19:13:20\",\"address\":{\"homeAddress\":\"家庭地址:四川\",\"schoolAddress\":\"学习地址:北京\"}}";
// 2.转换
Student student = JacksonUtil.jsonToBean(jsonStr, Student.class);
System.out.println(student);
}
/**
* 测试将json list字符串 转换成对应的List集合
*/
public static void testJsonToList(){
//1.准备数据
String jsonListStr = "[{\"id\":\"110\",\"name\":\"狗娃\",\"birthday\":\"2022-10-22 19:13:56\",\"address\":{\"homeAddress\":\"家庭地址:四川\",\"schoolAddress\":\"学习地址:北京\"}},{\"id\":\"120\",\"name\":\"狗剩\",\"birthday\":\"2022-10-22 19:13:56\",\"address\":{\"homeAddress\":\"家庭地址:湖南\",\"schoolAddress\":\"学习地址:上海\"}}]";
// 2.转换
List<Student> list = JacksonUtil.jsonToList(jsonListStr, Student.class);
System.out.println(list);
}
/**
* 测试将json set字符串 转换成对应的set集合
*/
public static void testJsonToSet(){
//1.准备数据 (这里面有两个一模一样的狗剩对象)
String jsonSetStr = "[{\"id\":\"110\",\"name\":\"狗娃\",\"birthday\":\"2022-10-22 20:03:42\",\"address\":{\"homeAddress\":\"家庭地址:四川\",\"schoolAddress\":\"学习地址:北京\"}},{\"id\":\"120\",\"name\":\"狗剩\",\"birthday\":\"2022-10-22 20:03:42\",\"address\":{\"homeAddress\":\"家庭地址:湖南\",\"schoolAddress\":\"学习地址:上海\"}},{\"id\":\"120\",\"name\":\"狗剩\",\"birthday\":\"2022-10-22 20:03:42\",\"address\":{\"homeAddress\":\"家庭地址:湖南\",\"schoolAddress\":\"学习地址:上海\"}}]";
// 2.转换 (转换后只打印了一次狗剩对象)
Set<Student> set = JacksonUtil.jsonToSet(jsonSetStr, Student.class);
System.out.println(set);
}
/**
* 测试json字符串 转换成map对象
*/
public static void testJsonToMap(){
//1.准备数据
String jsonMapStr = "{\"id\":\"110\",\"name\":\"狗娃\",\"birthday\":\"2022-10-22 20:08:46\",\"address\":{\"homeAddress\":\"家庭地址:四川\",\"schoolAddress\":\"学习地址:北京\"}}";
// 2.转换
Map<String, Object> map = JacksonUtil.jsonToMap(jsonMapStr, String.class, Object.class);
Objects.requireNonNull(map).forEach((k, v)-> System.out.println(k + "===>" + v));
}
}
3.4 jackson常用注解
@JsonFormat(pattern=”yyyy-MM-dd HH:mm:ss”) // 定义日期时间格式
@JsonProperty(“alia”) // 指定字段转换成json时使用的别名
@JsonIgnore // 放到某个字段上后, 转换成json时会忽略这个字段
3.5 解决json响应前台中文乱码的问题
我们随便编写一个User的实体类,然后我们去编写我们的测试Controller;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
编写一个Controller
@RestController
public class UserController {
//produces:指定响应体返回类型和编码
@RequestMapping(value = "/json1")
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User("秦疆1号", 3, "男");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(user);
//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
return str;
}
}
配置Tomcat,启动测试一下!
发现出现了乱码问题,我们需要设置一下他的编码格式为utf-8,以及它返回的类型;
通过@RequestMaping的produces属性来实现,修改下代码
//produces:指定响应体返回类型和编码
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")
再次测试, http://localhost:8080/json1 , 乱码问题OK!
【注意:使用json记得处理乱码问题】
乱码统一解决
上一种方法比较麻烦,如果项目中有许多请求则每一个都要添加,可以通过Spring配置统一指定,这样就不用每次都去处理了!
我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置!
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
3.6 SpringBoot整合jackson
3.6.1 SpringBoot中配置jackson日期格式
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
3.6.2 SpringBoot中解决json响应中文乱码的问题
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
@Bean
public HttpMessageConverter responseBodyConverter(){
//解决返回值中文乱码
StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(responseBodyConverter());
}
}
第4章fastjson框架的使用
4.1 注意最好不要用这个框架
fastjson经常爆安全漏洞, 另外现在fastjson已经改名升级为fastjson2了
4.2 将json转成java对象
String str = "{'name':'parkour'}"
Student s = JSON.parseObject(str,Student.class)
4.3 将java对象转成json格式字符串
Student student = new Student("110","狗娃");
String jsonstring = JSON.toJSONString(student);
4.4 将json数组转成java对象的List结合
String jsonArrayString = "[{'name':'狗娃'},{'name':'狗剩'}]"
List<Student> list = JSON.parseArray(jsonArrayString,Student.class);
4.5 将java对象的List集合转成json数组格式字符串
Student student1 = new Student("110","狗娃");
Student student2 = new Student("120","狗剩");
List<Student> list = new ArrayList<>();
list.add(student1);
list.add(student2);
String jsonArrayString = JSON.toJSONString(list);