JSON——学习笔记(消息转换器等)

7 篇文章 0 订阅
5 篇文章 0 订阅

参考/摘录书籍:Spring+Spring MVC+MyBatis整合开发 著○陈学明
参考图片:来自网络/自己提供
说明:本人相关博客仅供学习参考!

一、JSON介绍

  JSON以键值对格式表示数据,它相比XML等格式更为简洁。
  JSON (JavaScript Object Notation)即JavaScript对象图谱,是一种在Web中广泛使用的数据交换格式。
  JSON是轻量级的文本数据交换格式,它独立于语言,更易理解。
  轻量级是指和XML比较,json数据体积更小(节省流量),传输更快,更易解析。
  JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台。 目前非常多的动态编程语言(PHP,JSP,.C#等)都支持JSON。

1.1 JSON格式规范

  JSON格式可以用来表示对象和数组。
  标准JSON格式要求对象中的属性名(key)要使用双引号包起来,每个键值对之间使用逗号进行分隔。属性值可以是数字、字符串、数组或其它json对象。

1.1.1 对象 的表示

  • 使用大括号({ })表示对象;
  • 括号里面使用键值对方式添加属性,字符串的键和值分别使用双引号(")包起来。(在JS代码中,键值的双引号可以不加 【强烈要求按照标准格式书写】
  • 键和值之间使用冒号(:)分隔;
  • 多个属性之间使用逗号(,)分隔;
//JSON对象的表示示例:
{"name":"zhang liang","age":"18"}

1.1.2 数组 的表示

  • 数组用中括号([ ])包装;
  • 数组的元素可以使字符串,也可以是JSON的对象;
  • 多个元素之间也是使用逗号(,)分隔;
//JSON数组的表示示例:
["Jack Ma","Zhang SanFeng"]		//字符串元素的数组
[{"name":"zhang liang","age":"18"},{"name":"zhang liang","age":"18"}]	//JSON对象元素的数组

二、JSON在JavaScript中的使用

2.1 案例

  1. 在JavaScript中,直接以{}[]定义的JSON对象和数组变量的数据类型都是object,使用instanceof可以将二者区分。
	<script>
		var userObje = {"name":"zhang liang","age":"18"};	//JSON对象变量
		var userArray = [{"name":"li si","age":"22"},{"name":"wang wu","age":"30"}];	//JSON数组变量
		console.log(userObje)
		console.log(userArray)
		alert(typeof(userObje) == "object")		//true	对象数据类型的字符串
		alert(typeof(userArray) == "object") 	//true	数组数据类型的字符串,和对象是一样的
		alert(userObje instanceof Object) 		//true	JSON对象是Object对象的实例
		alert(userArray instanceof Array) 		//true	JSON对象是Array类型的实例
	</script>

在这里插入图片描述
2. 如果JSON对象和数组的最外层使用单引号或者双引号包起来,则这个变量就变成了一个字符串类型的变量了

	<script>
		var userObjeStr = '{"name":"zhang liang","age":"18"}';	//JSON对象变量-->字符串类型变量
		alert(typeof(userObjeStr) == "string")//true
		var userArrayStr = '[{"name":"li si","age":"22"}]';		//JSON数组变量
		alert(typeof(userArrayStr) == "string")//true
		console.log(userObjeStr)
		console.log(userArrayStr)
	</script>

在这里插入图片描述

2.2 JSON.parse()和JSON.stringify()

JSON.parse()JSON.stringify()函数实现JSON对象类型和JSON字符串类型的转换。

var userObj = JSON.parse(userObjeStr);		//JSON字符串转换为JSON对象
var userObjStr = JSON.stringify(userObj)	//JSON对象转JSON字符串
console.log(userObj)
console.log(userObjStr)

在这里插入图片描述

【注意】JSON.parse方法要求json串是标准json格式,即每个属性名都要用双引号包住。

2.3 获取元素值

  获取JSON对象中的属性值的两种方式:

  1. 格式对象.属性名。【如果属性包含空格的话,这种方式就不适用!】
  2. 格式对象["属性名"]。【可以处理属性包含空格的情况!】
var userObje1 = {"name":"zhang liang","age":"18"};
var userName = userObje1.name;	//属性名没有空格使用 ".属性名" 访问属性值
console.log(userName);

var userObje2 = {"user name":"zhang liang","age":"18"};
var userName2 = userObje2["user name"]; //属性名有空格使用 "对象["属性名"]" 访问属性值
console.log(userName2);

  获取JSON数组中的元素的方式:

//JSON字符串元素的数组
var userArray1 = ["zhang san","li si","wang wu"];
var userName1_0 = userArray1[0];
console.log(userName1_0);	//zhang san

//JSON对象元素的数组
var userArray2 = [{"name":"li si","age":"22"},{"name":"wang wu","age":"30"}];
var userName2_0 = userArray2[0].name;
var userAge2_0 = userArray2[0].age;
console.log(userName2_0);	//li si
console.log(userAge2_0);	//22

2.4 添加元素

<script>
	var userObj = {"name":"zhang san","age":"18"};
	userObj.name = "Li Si";				//修改旧的属性值
	userObj.birthDay = "2021-09-18";	//添加新的属性并赋值
	console.log(userObj);
		
	var userArray = [{"name":"Zhang San","age":"22"}];
	var userObj2 = {"name":"Wang Wu","age":"32"};
	userArray.push(userObj2);	//添加数组元素
	console.log(userArray);
</script>

在这里插入图片描述

2.5 元素遍历

【扩展】in 关键字的使用和for in 循环遍历对象的属性:

in关键字的使用

  • 作用:判断某个属性是否属于对象;
  • 格式:属性名称 in 对象名称 ;
  • 返回值:如果返回的结果为true,则表示该对象有这个属性,否则没有;

for in 循环遍历对象的属性

<script>
	var userObj = {"name":"zhang san","age":"18"};
	for(var attr in userObj){
		//此时attr表示对象的属性
		console.log(attr+'----'+userObj[attr]);
	}
</script>

在这里插入图片描述
数组对象的length 属性可以获得数组的元素个数。

var userArray = [{"name":"Zhang San","age":"22"},{"name":"Wang Wu","age":"32"}];
for (var i = 0; i < userArray.length; i++) {
	console.log(userArray[i]);
	console.log(userArray[i].name+"---"+userArray[i].age);
}

在这里插入图片描述

三、JSON在Java中的使用

常见JSON工具包:FastJson、Jackson

  • 序列化:就是把javaBean对象或集合转换为json字符串。
  • 反序列化:就是把json字符串转换为javaBean对象或集合。

3.1 Fastjson

  Fastjson是阿里巴巴开发的一套Java JSON库,Fastjson在所有的JavaJSON库中速度最快。使用时Maven导入配置如下:

<!-- 引入Fastjson依赖 -->
<dependency>
	<groupId>com.alibaba</groupId>      <!-- 组名 -->
	<artifactId>fastjson</artifactId>   <!-- 组件名 -->
	<version>1.2.78</version>           <!-- 版本 -->
</dependency>

3.1.1 常见API

方法描述
public static final Object parse(String text)把JSON文本parse为JSONObject或者JSONArray
public static final JSONObject parseObject(String text)把JSON文本parse成JSONObject
public static final T parseObject(String text, Class<T> clazz)把JSON文本parse为JavaBean(反序列化)
public static final JSONArray parseArray(String text)把JSON文本parse成JSONArray
public static final List parseArray(String text, Class<T> clazz)把JSON文本parse成JavaBean集合
public static final Object toJSON(Object javaObject)将JavaBean转换为JSONObject或者JSONArray
public static final String toJSONString(Object object)将JavaBean序列化为JSON文本(序列化)
public static final String toJSONString(Object object, boolean prettyFormat)将JavaBean序列化为带格式的JSON文本

3.1.2 序列化&反序列化

//序列化
    //toJSONString(Object object):将JavaBean对象或集合序列化为JSON文本
    //toJSONString(Object object, boolean prettyFormat):将JavaBean对象或集合序列化为带格式的JSON文本
    @Test
    public void test1(){
        User u1 = new User(1001,"许褚","上海浦东新区");
        User u2 = new User(1002,"小红","安徽省合肥市");
        List<User> userList = Arrays.asList(u1, u2);
        String u1Str = JSON.toJSONString(u1);
        String uListStr = JSON.toJSONString(userList);
        System.out.println("u1Str:"+u1Str);
        System.out.println("uListStr:"+uListStr);
        //带格式的JSON文本
        String u1StrFormat = JSON.toJSONString(u1, true);
        String uListStrFormat = JSON.toJSONString(userList, true);
        System.out.println(u1StrFormat);
        System.out.println(uListStrFormat);
    }

在这里插入图片描述

//反序列化
    //parseObject(String text, Class<T> clazz); // 把JSON文本转换为JavaBean对象
    //parseArray(String text, Class<T> clazz); //把JSON文本转换成JavaBean的集合
    //不要求Json串里是标准的json格式【注意!!】
    @Test
    public void test2(){
        String jsonStr = "{\"address\":\"上海浦东新区\",\"id\":1001,\"name\":\"许褚\"}";
        String jsonListStr = "[{\"address\":\"上海浦东新区\",\"id\":1001,\"name\":\"许褚\"},{\"address\":\"安徽省合肥市\",\"id\":1002,\"name\":\"小红\"}]";
        //JSON文本 --> JavaBean对象
        User user = JSON.parseObject(jsonStr, User.class);
        System.out.println("user:"+user);
        //JSON文本 --> JavaBean集合
        List<User> userList = JSON.parseArray(jsonListStr,User.class);
        System.out.println("userList:"+userList);
    }

在这里插入图片描述

3.1.3 JSON字符串和数组互转

@Test
public void test0(){
	int[] ints = {1,2,3,4,5};
	//整型数组转换为JSON数组字符串
	String arrayJsonStr = JSON.toJSONString(ints);
	System.out.println(arrayJsonStr);//[1,2,3,4,5]
	//数组字符串转换为整型数组
	int[] intsNew = JSON.parseObject(arrayJsonStr,ints.getClass());
	System.out.println(intsNew);//[I@262b2c86
}

3.1.4 取JSON字符串中的属性名或属性值

@Test
void test2(){
    String str = "";
    String keyProps = "{\"颜色\":\"玛莎拉蒂红\",\"配置\":\"(经典版,前碟后鼓,60/72V通用,裸车)\"}";
    HashMap map = JSON.parseObject(keyProps, LinkedHashMap.class);
    for (Object o : map.keySet()) {
        str += map.get(o);
    }
    System.out.println(str);
}

运行结果

3.2 Jackson

  Jackson可以将Java对象转换成JSON对象和XML文档,同样也可以价格JSON对象和XML文档转换为Java对象。其三个依赖包为:

  • jackson-core :核心包
  • jackson-annotations :注解功能包
  • jackson-databind :数据绑定包

使用时Maven导入配置如下:

<!-- 引入jackson依赖(提供转换器,把bean或集合转换为json串) -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.9.0</version>
</dependency>

在这里插入图片描述

3.2.1 注意事项

  • 默认情况下,ObjectMapper 在序列化对象时,将实体所有的字段一 一序列化,无论这些字段是否有值,是否为 null。
  • 如果实体中的某个字段没有提供 getter 方法,则该字段不会被序列化。
  • 操作JSON:databind(数据绑定) - ObjectMapper实例 读/写 JSON 是 POJO 序列化与反序列化 json 最方便的方式。(还有额外两种方式)

  Jackson使用对象封装器类(ObjectMapper)实例对对象和数组类型进行转换;writeValueAsString()将Java对象、数组和集合类型对象转换为JSON对象和数组字符串;readValue使用JSON格式字符串转换成Java对象。【ObjectMapper 主要用于对 Java 对象(例如 POJO、List、Set、Map 等)进行序列化与反序列化】

3.2.2 常见API

方法描述
void writeValue(File resultFile, Object value)将 java 对象序列化并写入指定文件中
String writeValueAsString(Object value)1. 将Java对象、数组、集合转换为JSON对象和数组字符串;
2. 如果 value 为 null,返回序列化的结果也返回 null;
T readValue(String jsonStr, Class<T> valueType)1. 从给定的 JSON 字符串反序列化为 Java 对象;
2. 如果jsonStr为空或者null,都会报错;
3. valueType 表示反序列化的结果对象,可以是任何 java 对象(POJO、Array、List、Set、Map 等)
T readValue(File src, Class<T> valueType)将本地 json 内容的文件反序列化为 java 对象

3.2.3 案例

//序列化【把JavaBean对象或集合转换为json字符串】
    @Test
    public void test1(){
        User u1 = new User(1001,"许褚","上海浦东新区");
        User u2 = new User(1002,"小红","安徽省合肥市");
        List<User> userList = Arrays.asList(u1, u2);
        //对象封装器类
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            //javabean对象转序列化【调用:objectMapper.writeValueAsString(beanObj或者listObj)】
            String u1Str = objectMapper.writeValueAsString(u1);
            //集合序列化
            String uListStr = objectMapper.writeValueAsString(userList);
            System.out.println("u1Str: "+u1Str);
            System.out.println("uListStr: "+uListStr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述

//反序列化就是把json字符串转换为javaBean对象或集合。
    @Test
    public void test2(){
        //readValue(String jsonStr, Class<T>  cls):转换为javaBean对象
        //【要求】Json串里是标准的json格式("属性名")
        String jsonStr = "{\"id\":1001,\"name\":\"许褚\",\"address\":\"上海浦东新区\"}";
        //对象封装器类
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(jsonStr,User.class);
            System.out.println("user:"+user);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //readValue(String jsonStr, JavaType javaType):转换为集合
        //【要求】Json串里是标准的json格式("属性名")
        String jsonList = "[{\"id\":1001,\"name\":\"许褚\",\"address\":\"上海浦东新区\"},{\"id\":1002,\"name\":\"小红\",\"address\":\"安徽省合肥市\"}]";
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class,User.class);
        try {
            List<User> userList = objectMapper.readValue(jsonList,javaType);
            for (User user : userList) {
                System.out.println("userList中的user:"+user);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述

详细可参考:Jackson API详细汇总

四、Spring MVC使用JSON

  浏览器页面局部以Ajax返回 application/json 内容类型的JSON数据响应,前端结合数据更新来刷新页面局部;
  Spring MVC 支持不同内容类型的处理请求;使用 HTTP 消息转换器(HttpMessageConverter)对前端请求内容和响应进行转换。spring-web 模块中提供了 JSON 类型的 HTTP 消息转换器子类,底层使用 Jackson 或 Gson 库进行 JSON 类型和 Java 对象类型的转换,对应的消息转换器类分别为:MappingJackson2HttpMessageConverterGsonHttpMessageConverter 。使用不同的 JSON 消息转换器需要导入对应的 JSON 依赖包。

4.1 JSON 依赖和消息转换器

  Spring Boot默认使用JSON作为响应格式,自带Jackson库进行转换。
  Spring MVC没有自带JSON数据转换包,但提供了Jackson的HTTP消息转换器,需要导入Jackson依赖。Jackson消息转换器一般不需要配置,自定义设置的话可以通过<mvc:annotation-driven>的<mvc:message-converters>子标签进行配置。

<!-- 注解驱动(会自动注册映射处理器和处理器适配器和参数转换注解) -->
<mvc:annotation-driven>
	<!-- MVC 消息转换器配置,配置不同的消息转换器类的 Bean -->
	<mvc:message-converters>
		<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
		<bean class="org.springframework.http.converter.json.GsonHttpMessageConverter" />
	</mvc:message-converters>
</mvc:annotation-driven>

  也可以使用 FastJson 作为 Spring MVC 的 HTTP 消息转换器。Spring MVC 默认没有提供其对应的消息转换器,但 FastJson 提供了 Spring 使用转换器类,所以除了导入依赖包之外,还需要配置相应的转换器 Bean。如下:

<!-- 注解驱动(会自动注册映射处理器和处理器适配器和参数转换注解) -->
<mvc:annotation-driven>
	<!-- MVC 消息转换器配置,配置不同的消息转换器类的 Bean -->
	<mvc:message-converters>
		<!-- FastJson 消息转换器 Bean -->
		<bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter" >
			<!-- 支持的内容类型 -->
			<property name="supportedMediaTypes" >
				<list>
					<value>text/html;charset=UTF-8</value>
					<!-- JSON格式的数据类型 -->
					<value>application/json;charset=UTF-8</value>
				</list>
			</property>
		</bean>
	</mvc:message-converters>
</mvc:annotation-driven>

备注:Java版的配置只需要在配置类(@Configuration,@Component等注解标注的类)添加该消息转换器的Bean组件即可。如下:

@Configuration
public class SpringApplicationConfig {

    /**
     * 将Message的有效负载从序列化形式转换为类型化对象的转换器,反之亦然。
     * @return 指定的消息转换器的实现类
     */
    @Bean
    public MessageConverter messageConverter(){
        return new MappingJackson2MessageConverter();
    }

}

4.2 JSON 内容类型的数据返回

  导入 JSON 依赖包,并将 Java 对象转换为 JSON 字符串后,就可以使用 response 对象返回 application/json 内容类型的 JSON 字符串。结合消息转换器,可以在控制器类和映射方法中使用 @ResponseBody 注解,由容器自动处理 Java 对象的转换并返回。

4.2.1 方式1:使用 HttpPServletResponse指定

  通过 HttpServletResponse 指定返回的内容类型为 application/json 的字符串。使用 response.getWriter().wirite()response.getOutputStream().print() 都可以将 Json字符串响应到前端。

@GetMapping("getJsonData")
public void jsonResponse(HttpServletResponse resp,HttpServletRequest req) throws Exception{
	//将发送到客户端的响应的字符编码(MIME 字符集)设置为 UTF-8
	resp.setCharacterEncoding("UTF-8");
	//设置发送到客户端的响应的内容类型
	resp.setContentType("application/json");
	User user = new User(1001,"Li Hua",18);
	//将 Jackson 的 ObjectMapper 转换实例
	ObjectMapper mapper = new ObjectMapper();
	//将 Java 对象转换为 JSON 字符串
	String userJsonStr = mapper.writeValueAsString(user);
	//从 response 对象获取 PrintWriter 输出流对象
	PrintWriter out = resp.getWriter();
	//往对象中写入一个字符串
	out.write(userJsonStr);
	//将缓冲输出到页面
	out.flush();
}
@GetMapping("getJsonData")
public void jsonResponse(HttpServletResponse resp,HttpServletRequest req) throws Exception{
	//将发送到客户端的响应的字符编码(MIME 字符集)设置为 UTF-8
	resp.setCharacterEncoding("UTF-8");
	//设置发送到客户端的响应的内容类型
	resp.setContentType("application/json");
	User user = new User(1001,"Li Hua",18);
	//将 Jackson 的 ObjectMapper 转换实例
	ObjectMapper mapper = new ObjectMapper();
	//将 Java 对象转换为 JSON 字符串
	String userJsonStr = mapper.writeValueAsString(user);
	//从 response 对象获取 PrintWriter 输出流对象
	PrintWriter out = resp.getWriter();
	//通过输出流 OutPutStream 对象输出字符串
	resp.getOutputStream().print(userJsonStr);
	//将缓冲输出到页面
	resp.getOutputStream.flush();
}

在这里插入图片描述

4.2.2 方式2:使用 @ResponseBody 注解

  @ResponseBody 可以使用在映射注解的方法上,容器内部通过 HttpMessageConverter 将方法返回的 Java 对象转化为 JSON 字符串后写入 Response 对象的 body 数据体中。

@ResponseBody
@GetMapping("getJsonDataAnnotation")
public User respUserJsonStr(){
	return new User(2002,"Li Bai",500);
}

在这里插入图片描述

【拓展】

  1. @ResponseBody 使用在控制器类中是,则该控制器所有的请求映射方法都是 JSON 类型的返回。
  2. @RestController 注解= @Controller 注解+@ResponseBody 注解的组合。

4.3 JSON 类型的请求参数匹配(@RequestBody)

  在 Spring MVC 的请求映射方法参数中,使用 @RequestParam 注解或不使用注解,Spring MVC 容器会自动进行参数的匹配并组装成对应的方法参数定义的类对象。
  默认情况下请求参数传递的内容类型是 application/x-www-form-urlencode,参数以键值对的方式传递(如:id=“1001”&name=“zhagnsan”)。如果需要传递 JSON 类型的请求参数,需要设定请求头的 ContentType : "application/json" ,后端方法参数使用 @RequestBody 注解进行匹配。

浏览器端

<script>
	//标准 json 字符串格式
	var loginUser = {"loginId":10001,"loginName":"zhang san"}
	$.ajax({
		url : "login",  //请求的 URL 地址
		type : "post",  //请求方法
		async : true,   //异步设置
		contentType : "application/json",   //设置发送到客户端的响应的内容类型
		data : JSON.stringify(loginUser),   //JSON对象转JSON字符串(发送到服务器的数据)
		dataType : 'json',  //从服务器返回的数据类型
		success : function(data){
			//请求成功后的回调方法,data就是返回的数据
		}
	})
</script>

服务端

/**
 * 此时该注解将请求体中的json绑定到对象的属性上
 */
@GetMapping("login")
public User getUserWithJson(@RequestBody User user){
	return user;
}

4.4 LocalDateTime的json格式化解决方案

如果想要让返回的json数据中,LocalDateTime类型是按照 yyyy-MM-dd HH:mm:ss 格式显示,有两种方案:

4.4.1 @JsonFormat 注解(方案一)

该方案局部生效

//如果时区显示不正确的话,可以添加timezone属性,如下:
//timezone = "GMT+8" 或 timezone = "Asiz/Shanghai"
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private LocalDateTime createTime;

4.4.2 全局配置方案(方案二)

该方案使用一个配置类,全局生效

1)在全局配置文件中配置(application.yml):

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: Asia/Shanghai #或 GMT+8

2)写一个配置类:

@Configuration
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format}")
    private String pattern;

    public LocalDateTimeSerializer localDateTimeSerializer(){
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
        //serializerByType:为给定类型配置自定义序列化程序。
        return builder -> builder.serializerByType(LocalDateTime.class,localDateTimeSerializer());
    }

}

4.5 将接收时间戳或时间字符串转为 LocalDateTime

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime frontImageTime;

备注:

  • @JsonFormat:主要是后台到前台的时间格式的转换;
  • @DataFormat:主要是前后到后台的时间格式的转换;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值