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 ...
随机推荐
- Fences桌面图标分类
1.简介 Fences也称为栅栏桌面, 可以用来分类和组织桌面上的图标. Fences可以将不同的图标放到不同的容器当中, 还可以自由的设置这个容器,比如移动和拉伸等等. 这样图标分类后,桌面就整洁多 ...
- PL/SQL连接时,报无法解析指定的字符串
前言: 工作原因,需要安装PL/SQL连接数据,oracle和PL/SQL都装好了,环境变量也配好了,启动PL/SQL进行连接数据库,结果报"无法解析指定的字符串",连接失败了. ...
- vue - 搭建 webapp 自适应项目-使用 vant 组件库 并 可自动调节大小
1.创建个vue 项目,这里不详细写怎么创建,参考 vue - 指令创建 vue工程 - 岑惜 - 博客园 (cnblogs.com) https://www.cnblogs.com/c2g52013 ...
- Oracle - 以 INSERT SQL语句形式导出结果集
使用 SQLcl - 这是 SQL Developer 的命令行接口 下载 SQLcl sql sys/welcome@localhost:1521:orcl as sysdba #sql usern ...
- sqlcl - Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
运行sqlcl的命令sql出错 bash-4.2$ sql username/password@hostname:1521:databasename Exception in thread " ...
- react中实现css动画
- Nginx虚拟主机、日志排错、模块配置
目录 Nginx虚拟主机 1. 基于多IP的方式 2. 基于多端口的方式 3. 基于多域名的方式 Nginx日志 Nginx配置文件配置项 Nginx模块 Nginx访问控制模块 Nginx状态监控模 ...
- 使用.NET 6开发TodoList应用(27)——实现API的Swagger文档化
系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 在日常开发中,我们需要给前端提供文档化的API接口定义,甚至需要模拟架设一个fake服务用来调试接口字段.或者对于后端开发人员 ...
- MINItest软件架构总结
MINItest软件架构总结 ----helloWen MINItest软件架构总结1. Problem Description2. Analysis3. Solution3.1. 通过读取设备信息来 ...
- 在Rainbond上使用Locust进行压力测试
Locust简介 Locust 是一种易于使用.可编写脚本且可扩展的性能测试工具.并且有一个用户友好的 Web 界面,可以实时显示测试进度.甚至可以在测试运行时更改负载.它也可以在没有 UI 的情况下 ...