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

25 篇文章 7 订阅
17 篇文章 0 订阅

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


请求的参数我们可以显示的声明出来,比如我们需要前端在查询的时候,传过来一个符合Mine对象格式的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;
	}





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




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





如何做到的呢?



一、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项目的话,只需要添加如下依赖






二、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 yukun24@126.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)







(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 yukun24@126.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)运行测试方法

五、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 yukun24@126.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;
	}

}



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






  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值