在日常开发与数据库打交道的时候,常有以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即可。


参考:

JSON一文通透,Java、JS与JSON互转

Fastjson 简明教程 | 菜鸟教程 (runoob.com)

FastJSON解析Json字符串(反序列化为List、Map)的更多相关文章

  1. Scala中使用fastJson 解析json字符串

    Scala中使用fastJson 解析json字符串 添加依赖 2.解析json字符 2.1可以通过JSON中的parseObject方法,把json字符转转换为一个JSONObject对象 2.2然 ...

  2. 将JSON字符串反序列化为指定的.NET对象类型

    目录导航: 前言: 方法一.在项目中定义对应的对象参数模型,用于映射反序列化出来的参数(复杂JSON字符串数据推荐使用): 方法二.直接将JSON字符串格式数据反序列化转化为字典数据(简单JSON字符 ...

  3. fastjson 将json字符串转化成List<Map<String, Object>>

    亲测可行,如下: JSON.parseObject(jsonstr, new TypeReference<List<Map<String, Object>>>() ...

  4. 用阿里fastJson解析Json字符串

    一下总结来自工作代码: 1.第一种情况: 通过服务器端发送http请求获取的接送字符串. String jsonStr = HttpRequestUtil.sendGet(config.getAddr ...

  5. fastjson将json字符串转化为java对象

    目录 一.导入一个fastjson的jar包 二.Json字符串格式 三.根据json的格式创建Java类 四.给java类的所有属性添加setter方法 五.转换为java对象 一.导入一个fast ...

  6. [K/3Cloud]将JSON字符串反序列化为C#动态对象

    using Kingdee.BOS.Util; string errString="{/"Row/":1,/"PageId/":/"1234 ...

  7. 【Android进阶】Gson解析json字符串的简单应用

    在客户端与服务器之间进行数据传输,一般采用两种数据格式,一种是xml,一种是json.这两种数据交换形式各有千秋,比如使用json数据格式,数据量会比较小,传输速度快,放便解析,而采用xml数据格式, ...

  8. 使用 dynamic 标记解析JSON字符串 JDynamic :支持Json反序列化为Dynamic对象

    使用 dynamic 标记解析JSON字符串  http://www.cnblogs.com/taotaodetuer/p/4171327.html 1 string jsonStr = " ...

  9. fastjson将json字符串转化成map的五种方法

    package com.zkn.newlearn.json; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObj ...

随机推荐

  1. Linux无法登陆,var目录权限修改导致SSH失败

    1.问题说明 Linux远程服务器突然无法SSH登录了, 登陆报错: ssh_exchange_identification: read: Connection reset by peer. 2.问题 ...

  2. 使用docker-compose部署Kafka集群

    之前写过Kafka集群的部署,不过那是基于宿主机的,地址:Kafka基础教程(二):Kafka安装 和Zookeeper一样,有时想简单的连接Kafka用一下,那就需要开好几台虚拟机,如果Zookee ...

  3. ARM微处理器的七种运行模式

    ARM微处理器的七种运行模式: 用户模式(usr):正常的程序执行状态 快速中断模式(fiq):用于处理快速中断,对高速数据传输或通道处理. 中断模式(irq):对一般情况下的中断进行处理. 管理模式 ...

  4. CSS基础 行内元素/行内块元素设置垂直对齐方式及常见使用案例

    vertical-align 属性值 效果 baseline 基线对齐 top 顶部对齐 middle 中心对齐 bottom 底部对齐 使用案例1:百度搜索框左边和右边底部没有对齐 使用vertic ...

  5. 适配器模式(pthon)

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- # adapter_pattern.py # 适配器模式 class Adaptee: def reque ...

  6. SQLAlchemy(十)

    ORM操作在实际项目中的应用非常多,涉及到的框架也是根据不同的项目有不同的处理模块,不过操作流程和步骤都是大同小异基本没有什么太大变化,唯一需要注意的就是在实际操作过程中你要使用的ORM框架的处理性能 ...

  7. Go语言系列之包

    Go语言的包(package) 一.包介绍 包(package)是多个Go源码的集合,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmt.os.io等. 二.定义包 我们还可以根据自己 ...

  8. 硬核 - Java 随机数相关 API 的演进与思考(上)

    本系列将 Java 17 之前的随机数 API 以及 Java 17 之后的统一 API 都做了比较详细的说明,并且将随机数的特性以及实现思路也做了一些简单的分析,帮助大家明白为何会有这么多的随机数算 ...

  9. 金融云原生漫谈(三)|银行云原生基础设施构建:裸金属VS虚拟机

    在金融行业数字化转型的驱动下,国有银行.股份制银行和各级商业银行也纷纷步入容器化的进程.   如果以容器云上生产为目标,那么整个容器云平台的设计.建设和优化对于银行来说是一个巨大的挑战.如何更好地利用 ...

  10. 基于 Keras 实现图像风格转移

     Style Transfer 这个方向火起来是从2015年Gatys发表的Paper A Neural Algorithm of Artistic Style(神经风格迁移) , 这里就简单提一下论 ...