FastJSON解析Json字符串(反序列化为List、Map)
在日常开发与数据库打交道的时候,常有以Json格式的字符串存储到数据库的情况,当在Java程序中获取到对应的Json格式的String字符串后,如何才能转换为我们想要的数据格式(比如转换成Java中的自定义类等),就需要做出对Json数据解析的,而我最近写的接口就遇到了这样的需求,我借助阿里的Fastjson api实现json转化为Java POJO,现在进行简单的总结,记录一下。
配置maven依赖
分别引入三个依赖,分别是fastjson、lombok、commons工具包。
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
其中版本号我已经写上了,如有需要请使用特定版本,建议使用最新版。
数据准备
下面就简单构造一点数据,对数据解析的要求:整个json转化为一个POJO,其中 code、name类型为String,schedule类型为List<String>表示计划清单,completion类型为Map<String,String>表示完成情况一一映射。
构建周一到周日的 计划&完成情况 的json数据:
[
{
"code":"monday",
"name":"周一",
"schedule":"get_up_9am,exercise_one_hour,study_one_hour,goto_bed_before_12pm",
"completion":"get_up_9am=y,exercise_one_hour=n,study_one_hour=y,goto_bed_before_12pm=n"
},{
"code":"tuesday",
"name":"周二",
"schedule":"exercise_one_hour,study_one_hour,goto_bed_before_12pm",
"completion":"exercise_one_hour=y,study_one_hour=y,goto_bed_before_12pm=y"
},{
"code":"wednesday",
"name":"周三",
"schedule":"get_up_9am,exercise_one_hour,goto_bed_before_12pm",
"completion":"get_up_9am=n,exercise_one_hour=n,goto_bed_before_12pm=n"
},{
"code":"thursday",
"name":"周四",
"schedule":"",
"completion":""
},{
"code":"friday",
"name":"周五",
"schedule":"study_one_hour,goto_bed_before_12pm",
"completion":"study_one_hour=n,goto_bed_before_12pm=n"
},{
"code":"saturday",
"name":"周六",
"schedule":"goto_bed_before_12pm",
"completion":"goto_bed_before_12pm=n"
},{
"code":"sunday",
"name":"周日",
"schedule":"",
"completion":""
}
]
JSON格式字符串转Java对象
下面就是直接贴代码
DO&DTO
DO是全部为String类型的数据,DTO是其中的schedule为List,completion为Map格式的
WeekScheduleDO
package com.xxx;
import lombok.Data;
@Data
public class WeekScheduleDO {
private String code;
private String name;
private String schedule;
private String completion;
}
WeekScheduleDTO
package com.fast;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class WeekScheduleDTO {
private String code;
private String name;
private List<String> schedule;
private Map<String,String> completion;
}
SelfJSONUtils
把解析需要用到的方法自定义封装一下
package com.xxx;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
public class SelfJSONUtils {
public static List<WeekScheduleDTO> toWeekScheduleDOs(String str){
// String->List<WeekScheduleDO>
List<WeekScheduleDO> weekScheduleDOs = JSON.parseObject(str, new TypeReference<List<WeekScheduleDO>>() {});
List<WeekScheduleDTO> result = new ArrayList<>();
for (WeekScheduleDO item:weekScheduleDOs) {
result.add(toWeekScheduleDTO(item));
}
return result;
}
private static WeekScheduleDTO toWeekScheduleDTO(WeekScheduleDO item){
WeekScheduleDTO weekScheduleDTO = new WeekScheduleDTO();
weekScheduleDTO.setCode(item.getCode());
weekScheduleDTO.setName(item.getName());
// "schedule":"get_up_9am,..." 转换成lsit
String[] schedule = item.getSchedule().split(",");
weekScheduleDTO.setSchedule(Arrays.stream(schedule).filter(e -> StringUtils.isNoneBlank(e)).collect(Collectors.toList()));
// "completion":"get_up_9am=y,..." 转换成map
weekScheduleDTO.setCompletion(toMap(item.getCompletion().split(",")));
return weekScheduleDTO;
}
private static Map<String,String> toMap(String[] args){
Map<String,String> map = new HashMap<>();
for(String arg : args){
if(!arg.isEmpty()) {
String[] split1 = arg.split("=");
map.put(split1[0], split1[1]);
}
}
return map;
}
}
测试&调用
package com.xxx;
import java.util.List;
public class Demo {
public static void main(String[] args) {
String json = "[{\"code\":\"monday\",\"name\":\"周一\",\"schedule\":\"get_up_9am,exercise_one_hour,study_one_hour,goto_bed_before_12pm\",\"completion\":\"get_up_9am=y,exercise_one_hour=n,study_one_hour=y,goto_bed_before_12pm=n\"},{\"code\":\"tuesday\",\"name\":\"周二\",\"schedule\":\"exercise_one_hour,study_one_hour,goto_bed_before_12pm\",\"completion\":\"exercise_one_hour=y,study_one_hour=y,goto_bed_before_12pm=y\"},{\"code\":\"wednesday\",\"name\":\"周三\",\"schedule\":\"get_up_9am,exercise_one_hour,goto_bed_before_12pm\",\"completion\":\"get_up_9am=n,exercise_one_hour=n,goto_bed_before_12pm=n\"},{\"code\":\"thursday\",\"name\":\"周四\",\"schedule\":\"\",\"completion\":\"\"},{\"code\":\"friday\",\"name\":\"周五\",\"schedule\":\"study_one_hour,goto_bed_before_12pm\",\"completion\":\"study_one_hour=n,goto_bed_before_12pm=n\"},{\"code\":\"saturday\",\"name\":\"周六\",\"schedule\":\"goto_bed_before_12pm\",\"completion\":\"goto_bed_before_12pm=n\"},{\"code\":\"sunday\",\"name\":\"周日\",\"schedule\":\"\",\"completion\":\"\"}]";
List<WeekScheduleDTO> weekScheduleDTOS = SelfJSONUtils.toWeekScheduleDOs(json);
System.out.println(weekScheduleDTOS);
}
}
现在就可以直接运行或debug查看解析情况

这一个需求应该算常规复杂的情况,如果还有更为复杂的情况,转换形式也可以依葫芦画瓢整出来~
注意的点
如果你细心的话,你就会发现我的代码有一处做出了冗余的操作,它位于SelfJSONUtils#toBatchItemDTO的转换为List那里的Stream流处:
weekScheduleDTO.setSchedule(Arrays.stream(schedule).filter(e -> StringUtils.isNoneBlank(e)).collect(Collectors.toList()));
fastjson转换的时候,默认会把空的数据剔除掉,根据这一特性,我直接使用下面代码就行了(没有filter):
weekScheduleDTO.setSchedule(Arrays.stream(schedule).collect(Collectors.toList()));
其实不加 filter(e -> StringUtils.isNoneBlank(e)) 是不行的。在代码中的map转换的时候,确实是把空的数据剔除掉了,转map出来以后确实size=0(如下图),在转List的时候,不过来空数据的话,该数据就会以""的形式存储在List中(这个坑我半天!!)

除了上面使用 StringUtils#isNoneBlank 除空以外,还可以使用 e.hashCode()!=0 来解决,当然这是在没有StringUtils可用的情况下使用的策略
weekScheduleDTO.setSchedule(Arrays.stream(schedule).filter(e -> e.hashCode()!=0).collect(Collectors.toList()));
简单分析一下出现这种情况产生的原因:
fastjosn解析josn为POJO的时候,先会创建一个pojo空对象,之后通过实体类的set方法对参数进行赋值,由于fastjson解析时默认把为null的数据剔除掉了,所以fastjson没保留下的字段就不会进行set操作,而pojo类这个字段自始至终都没有被谁赋值,作为String类型就默认为"",而在转换为List的时候,就会直接存储进一个""(List可以存储多个"")。
这一个问题也许并不大,但是当业务需求就是因为这一个小点不能按照我们的思路去执行的时候,就很难找出这一个微小的问题。
另外,JSON数据反序列化为Java对象时,必须要有默认无参的构造函数,否则会报如下异常
com.alibaba.fastjson.JSONException: default constructor not found.
Fastjson API
Fastjson被公认为Java与json交互最快的库!简单看了一下Fastjson的api设计,对于序列化和发序列化json数据很多的可选操作,比如 @JSONField 、BeanToArray、ContextValueFilter 配置 JSON 转换、NameFilter 和 SerializeConfig等等。具体使用查阅官方API即可。
参考:
Fastjson 简明教程 | 菜鸟教程 (runoob.com)
FastJSON解析Json字符串(反序列化为List、Map)的更多相关文章
- Scala中使用fastJson 解析json字符串
Scala中使用fastJson 解析json字符串 添加依赖 2.解析json字符 2.1可以通过JSON中的parseObject方法,把json字符转转换为一个JSONObject对象 2.2然 ...
- 将JSON字符串反序列化为指定的.NET对象类型
目录导航: 前言: 方法一.在项目中定义对应的对象参数模型,用于映射反序列化出来的参数(复杂JSON字符串数据推荐使用): 方法二.直接将JSON字符串格式数据反序列化转化为字典数据(简单JSON字符 ...
- fastjson 将json字符串转化成List<Map<String, Object>>
亲测可行,如下: JSON.parseObject(jsonstr, new TypeReference<List<Map<String, Object>>>() ...
- 用阿里fastJson解析Json字符串
一下总结来自工作代码: 1.第一种情况: 通过服务器端发送http请求获取的接送字符串. String jsonStr = HttpRequestUtil.sendGet(config.getAddr ...
- fastjson将json字符串转化为java对象
目录 一.导入一个fastjson的jar包 二.Json字符串格式 三.根据json的格式创建Java类 四.给java类的所有属性添加setter方法 五.转换为java对象 一.导入一个fast ...
- [K/3Cloud]将JSON字符串反序列化为C#动态对象
using Kingdee.BOS.Util; string errString="{/"Row/":1,/"PageId/":/"1234 ...
- 【Android进阶】Gson解析json字符串的简单应用
在客户端与服务器之间进行数据传输,一般采用两种数据格式,一种是xml,一种是json.这两种数据交换形式各有千秋,比如使用json数据格式,数据量会比较小,传输速度快,放便解析,而采用xml数据格式, ...
- 使用 dynamic 标记解析JSON字符串 JDynamic :支持Json反序列化为Dynamic对象
使用 dynamic 标记解析JSON字符串 http://www.cnblogs.com/taotaodetuer/p/4171327.html 1 string jsonStr = " ...
- fastjson将json字符串转化成map的五种方法
package com.zkn.newlearn.json; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObj ...
随机推荐
- Eclipse提速优化方法
Eclipse提速优化方法 Eclipse运行太慢了,尤其是导入大型maven项目的时候经常动不动就down掉,于是总结了一下Eclipse提速的方法. 1.关闭不常用的工程 打开的项目太多,会严重影 ...
- AES对称加密算法实现:Java,C#,Golang,Python
高级加密标准(Advanced Encryption Standard,简写AES),是一种用来替代DES的对称加密算法,相比DES,AES安全性更高,加密速度更快,因此被广泛使用. 理论上看,AES ...
- 『无为则无心』Python函数 — 34、lambda表达式
目录 1.lambda的应用场景 2.lambda语法 3.快速入门 4.示例:计算a + b 5.lambda的参数形式 6.lambda的应用 lambda表达式的主要作用就是化简代码. 匿名函数 ...
- linux分区(挂载)
主分区: 最多4个扩展分区: 最多一个: 扩展分区+主分区最多4个: 不能存放数据,只能划分逻辑分区逻辑分区: 可格式化.存放数据: 分区编号只能从5开始(1.2.3.4编号为主分区或扩展分区) 所有 ...
- 初识python 之 爬虫:爬取某网站的壁纸图片
用到的主要知识点:requests.get 获取网页HTMLetree.HTML 使用lxml解析器解析网页xpath 使用xpath获取网页标签信息.图片地址request.urlretrieve ...
- go.mod file not found in current directory or any parent directory; see 'go help modules'
go的环境设置问题,执行 go env -w GO111MODULE=auto 我的环境:Windows 7, Go 1.17 D:\Apps\GOPATH\src\code.oldboyedu.co ...
- Java 递归 常见24道题目 总结
1.N个台阶的走法递归[这里设为10个台阶] /** * N个台阶的走法递归 * <p> * 有个楼梯,台阶有10个,每次可以跳上1阶 或者 2阶 ,那么台阶的走法一共有多少种 */ @T ...
- spring boot 启动读取的配置文件优先级
1.优先级从高到低 1. file:/config/ 2. file:/ 3. classpath:/config/ 4. classpath:/ 所有位置的application.properti ...
- set类型转string[] 正确写法
测试源码: 1 @org.junit.Test 2 public void testSetType(){ 3 //测试set类型转string[] 4 // 5 Set<String> s ...
- 利用python绘制分析路易斯安那州巴吞鲁日市的人口密度格局
前言 数据来源于王法辉教授的GIS和数量方法,以后有空,我会利用python来实现里面的案例,这里向王法辉教授致敬. 绘制普查人口密度格局 使用属性查询提取区边界 import numpy as np ...