String[] 转 HashSet 和 List + ObjectMapper类的使用实现json的正反序列化
程序员文章站
2024-03-11 13:46:19
...
在做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 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)
(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)运行测试方法
五、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;
}
}
完整测试控制台效果展示如下: