欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化

程序员文章站 2024-03-11 13:46:19
...

在做Java Web项目对外提供API的时候,比如Spring项目中,我们通常借助Controller来实现方法级别的Restful风格的接口的包装,当然有方法,就得有参数,参数有两类,一是请求的参数,一是返回的参数


请求的参数我们可以显示的声明出来,比如我们需要前端在查询的时候,传过来一个符合Mine对象格式的JSON串,我们可以定义方法如下


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化


演示查询效果如下:


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化



请求的参数我们也可以不声明出来,比如我们只规定前端发过来一个请求就行,关于请求的内容,我们在方法里面进行校验,如果通过了我们就反序列化为对象,方法如下


	@GetMapping("/query1")
	public ResponseResult Query1(HttpServletRequest request) {

		/**
		 * 公共接口类HttpServletRequest继承自ServletRequest.
		 * 客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。
		 * 所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。
		 * HttpServletResponse继承了ServletResponse接口,并提供了与Http协议有关的方法,
		 * 这些方法的主要功能是设置HTTP状态码和管理Cookie。
		 * 
		 * 拿到reques对象中请求的参数map集合,利用自定义的Json转换工具,实现参数反序列化成对象
		 */
		Map<String, String[]> parMap = request.getParameterMap();
		for (Map.Entry<String, String[]> params : parMap.entrySet()) {
			String key = params.getKey();
			String val = params.getValue()[0];
			System.err.println("参数名:" + key + ",参数值:" + val);
		}

		// 拿到参数map后,我们就可以根据参数map构建我们需要的类实例了,实现自定义对象的反序列化
		System.err.println("=====================================");
		Map<String, Object> jsonMap = new HashMap<>();
		for (Map.Entry<String, String[]> params : parMap.entrySet()) {
			String key = params.getKey();
			String val = params.getValue()[0];
			String[] valArray = val.split(",");
			if (key.equals("likes")) {
				jsonMap.put(key, JsonConventUtils.strArrayTostrSet(valArray));
			} else if (key.equals("nums")) {
				jsonMap.put(key, JsonConventUtils.strArrayTointSet(valArray));
			} else {
				jsonMap.put(key, val);
			}
		}

		String json = JsonConventUtils.mapTojson(jsonMap);
		Mine mine = (Mine) JsonConventUtils.jsonToobject(json, Mine.class);

		ResponseResult result = new ResponseResult(new ResultData<>(ResponseMessage.OK, mine));

		return result;
	}


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化



演示查询的效果如下(和上面的请求参数一样,不一样的是URI):


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化


后台输出request对象中的参数map集合信息如下


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化



如何做到的呢?



一、Spring-Boot -- Pom依赖如下



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.appleyk</groupId>
	<artifactId>spring-boot-web</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Java-Web</name>
	<packaging>war</packaging>
	<!-- 继承官网最新父POM【假设当前项目不再继承其他POM】 -->
	<!-- http://projects.spring.io/spring-boot/#quick-start -->
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
	</parent>
	<!-- 使用Java8,嘗試使用新特新【stream和lambda】 -->
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<repositories>
		<repository>
			<id>osgeo</id>
			<name>Open Source Geospatial Foundation Repository</name>
			<url>http://download.osgeo.org/webdav/geotools/</url>
		</repository>
	</repositories>
	<!-- Starter POMs是可以包含到应用中的一个方便的依赖关系描述符集合 -->
	<!-- 该Starters包含很多你搭建项目, 快速运行所需的依赖, 并提供一致的, 管理的传递依赖集。 -->
	<!-- 大多数的web应用都使用spring-boot-starter-web模块进行快速搭建和运行。 -->
	<!-- spring-boot-starter-web -->
	<!-- 对全栈web开发的支持, 包括Tomcat和 spring-webmvc -->
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
		</dependency>
		<!-- Spring 单元测试 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- 添加热部署 devtools:监听文件变动 -->
		<!-- 当Java文件改动时,Spring-boo会快速重新启动 -->
		<!-- 最简单的测试,就是随便找一个文件Ctrl+S一下,就可以看到效果 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<!-- optional=true,依赖不会传递 -->
			<!-- 本项目依赖devtools;若依赖本项目的其他项目想要使用devtools,需要重新引入 -->
			<optional>true</optional>
		</dependency>
		<!-- JUnit单元测试 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
	</dependencies>
</project>


当然,如果是Spring项目的话,只需要添加如下依赖


String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化




二、Json转换工具类


JsonConventUtils.java

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Json转换工具类
 * @author aaa@qq.com
 * @blob   http://blog.csdn.net/appleyk
 * @date   2018年3月29日-下午1:34:53
 */
public class JsonConventUtils {

	/**
	 * JSON序列化工具
	 * ObjectMapper类是Jackson库的主要类。
	 * 它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。
	 * 它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写
	 */
	static ObjectMapper mapper = new ObjectMapper();
		
	/**
	 * String数组转HashSet<String>
	 * 
	 * @param strArray
	 * @return
	 */
	public static HashSet<String> strArrayTostrSet(String[] strArray) {
		HashSet<String> sets = new HashSet<>();
		for (String str : strArray) {
			sets.add(str);
		}
		return sets;
	}

	/**
	 * String数组转HashSet<Long>
	 * 
	 * @param strArray
	 * @return
	 */
	public static HashSet<Long> strArrayTolongSet(String[] strArray) {
		HashSet<Long> sets = new HashSet<>();
		// 先转List<Long> -- 使用Java8特性 -- stream 配合 lamda表达式 -- 批量转化str数组 -->
		// long数组
		List<Long> list = Arrays.asList(strArray).stream().map(s -> Long.parseLong(s)).collect(Collectors.toList());
		for (Long n : list) {
			sets.add(n);
		}

		return sets;
	}

	/**
	 * String数组转HashSet<Long>
	 * 
	 * @param strArray
	 * @return
	 */
	public static HashSet<Integer> strArrayTointSet(String[] strArray) {
		HashSet<Integer> sets = new HashSet<>();
		// 先转List<Long> -- 使用Java8特性 -- stream 配合 lamda表达式 -- 批量转化str数组 --> long数组
		List<Integer> list = Arrays.asList(strArray).stream().map(s -> Integer.parseInt(s))
				.collect(Collectors.toList());
		for (Integer n : list) {
			sets.add(n);
		}
		return sets;
	}
	
	/**
	 * map 转 json字符串
	 * @return
	 */
	public static String mapTojson(Map<?, ?> map){
		try {
			return mapper.writeValueAsString(map);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		
		return null;
	}
	
	/**
	 * json字符串 转换 Java 对象
	 * @param json
	 * @param clazz
	 * @return
	 */
	public static Object jsonToobject(String json,Class clazz){
		
		try {
			Object object = mapper.readValue(json, clazz);
			return object;
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}
	
	/**
	 * 下面还可以自行添加其他序列化方法,省略.................
	 */
}




三、本篇用到的pojo类Mine



Mine.java(实现序列化)

import java.io.Serializable;
import java.util.HashSet;

public class Mine implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/*
	 * 用户ID
	 */
	private Long id;

	/*
	 * 喜欢的球星
	 */
	private HashSet<String> likes;

	/*
	 * 喜欢球星的球衣号码
	 */
	private HashSet<Integer> nums;

	public Mine() {
		likes = new HashSet<>();
		nums = new HashSet<>();
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public HashSet<String> getLikes() {
		return likes;
	}

	public void setLikes(HashSet<String> likes) {
		this.likes = likes;
	}

	public HashSet<Integer> getNums() {
		return nums;
	}

	public void setNums(HashSet<Integer> nums) {
		this.nums = nums;
	}
	
	@Override
	public String toString(){
		return "用户ID: "+id+",喜欢的球星有: "+likes+",球星的球衣号码有: "+nums;
	}
}




四、Json转换工具单元测试一把



(1)



String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化




(2)


JsonConventTest.java

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import com.appleyk.pojo.Mine;
import com.appleyk.utils.JsonConventUtils;

/**
 * Json转换根据测试
 * @author aaa@qq.com
 * @blob   http://blog.csdn.net/appleyk
 * @date   2018年3月29日-下午1:49:24
 */
public class JsonConventTest {

	@Test
	public void Test() {

		Map<String, Object> jsonMap = new HashMap<>();
		Long id = 1001L;
		String strlikes = "科比,詹姆斯,麦迪";
		String strnums = "24,23,1";

		/*
		 * 1. jsonMap添加第一个属性
		 */
		jsonMap.put("id", id);

		/*
		 * 2.strlikes 转成 对应的 Hash<String>,添加进jsonMap
		 */
		jsonMap.put("likes", JsonConventUtils.strArrayTostrSet(strlikes.split(",")));

		/*
		 * 3.strnums 转成 对应的 Hash<Integer>,添加进jsonMap
		 */
		jsonMap.put("nums", JsonConventUtils.strArrayTointSet(strnums.split(",")));

		// map 转 json 串
		String json = JsonConventUtils.mapTojson(jsonMap);
		System.out.println(json);

		System.out.println("上为map转成json字符串=======================下为json串序列化为对象");

		// 反序列化Json串 --> User对象
		Mine mine = (Mine) JsonConventUtils.jsonToobject(json, Mine.class);
		System.out.println(mine);

	}
}




(3)运行测试方法

String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化

五、Controller层完整代码

TestController.java

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.appleyk.pojo.Mine;
import com.appleyk.result.ResponseMessage;
import com.appleyk.result.ResponseResult;
import com.appleyk.result.ResultData;
import com.appleyk.utils.JsonConventUtils;

/**
 * 
 * @author aaa@qq.com
 * @blob http://blog.csdn.net/appleyk
 * @date 2018年3月29日-下午1:26:39
 */
@RestController // same as @Controller + @ResponseBody
@RequestMapping("/rest/v1.0.1/appleyk/test") // restful风格的api接口
public class TestController {

	@GetMapping("/query1")
	public ResponseResult Query1(HttpServletRequest request) {

		/**
		 * 公共接口类HttpServletRequest继承自ServletRequest.
		 * 客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。
		 * 所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。
		 * HttpServletResponse继承了ServletResponse接口,并提供了与Http协议有关的方法,
		 * 这些方法的主要功能是设置HTTP状态码和管理Cookie。
		 * 
		 * 拿到reques对象中请求的参数map集合,利用自定义的Json转换工具,实现参数反序列化成对象
		 */
		Map<String, String[]> parMap = request.getParameterMap();
		for (Map.Entry<String, String[]> params : parMap.entrySet()) {
			String key = params.getKey();
			String val = params.getValue()[0];
			System.err.println("参数名:" + key + ",参数值:" + val);
		}

		// 拿到参数map后,我们就可以根据参数map构建我们需要的类实例了,实现自定义对象的反序列化
		System.err.println("=====================================");
		Map<String, Object> jsonMap = new HashMap<>();
		for (Map.Entry<String, String[]> params : parMap.entrySet()) {
			String key = params.getKey();
			String val = params.getValue()[0];
			String[] valArray = val.split(",");
			if (key.equals("likes")) {
				jsonMap.put(key, JsonConventUtils.strArrayTostrSet(valArray));
			} else if (key.equals("nums")) {
				jsonMap.put(key, JsonConventUtils.strArrayTointSet(valArray));
			} else {
				jsonMap.put(key, val);
			}
		}

		String json = JsonConventUtils.mapTojson(jsonMap);
		Mine mine = (Mine) JsonConventUtils.jsonToobject(json, Mine.class);

		ResponseResult result = new ResponseResult(new ResultData<>(ResponseMessage.OK, mine));

		return result;
	}

	/**
	 * 不暴露HttpServletRequest,直接挂上Mine,由servlet自行匹配参数的类型并进行对象的反序列化
	 * @param mine
	 * @return
	 */
	@GetMapping("/query2")
	public ResponseResult Query2(Mine mine) {

		ResponseResult result = new ResponseResult(new ResultData<>(ResponseMessage.OK, mine));

		return result;
	}

}



完整测试控制台效果展示如下:



String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化