FastJSON解析Json字符串(反序列化为List、Map)

FastJSON解析Json字符串(反序列化为List、Map)文章目录配置 maven 依赖数据准备 JSON 格式字符串转 Java 对象 DO amp DTOSelfJSONU 测试 amp 调用注意的点 FastjsonAPI 在日常开发与数据库打交道的时候 常有以 Json 格式的字符串存储到数据库的情况 当在 Java 程序中获取到对应的 Json 格式的 String 字符串后 如何才能转换为我们想要的数据格式 比如转换成 Java 中的自定义类等 就需要做出对 Json 数据解析的 而我最近写的接口就遇到了这样的需求 我借助阿里的 Fastjsonapi 实现 json 转化为 JavaP

在日常开发与数据库打交道的时候,常有以Json格式的字符串存储到数据库的情况,当在Java程序中获取到对应的Json格式的String字符串后,如何才能转换为我们想要的数据格式(比如转换成Java中的自定义类等),就需要做出对Json数据解析的,而我最近写的接口就遇到了这样的需求,我借助阿里的Fastjson api实现json转化为Java POJO,现在进行简单的总结,记录一下。

配置maven依赖

分别引入三个依赖,分别是fastjson、lombok、commons工具包。

<dependencies>  
    <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>  
             <dependency> <groupId>org.apache.commons 
              groupId> <artifactId>commons-lang3 
               artifactId> <version>3.12.0 
                version>  
                 dependency>  
                  dependencies> 

其中版本号我已经写上了,如有需要请使用特定版本,建议使用最新版。

数据准备

下面就简单构造一点数据,对数据解析的要求:整个json转化为一个POJO,其中 code、name类型为String,schedule类型为List

表示计划清单,completion类型为Map

表示完成情况一一映射。

构建周一到周日的 计划&完成情况 的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 
    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转换的时候,默认会把为null的数据剔除掉(可选),根据这一特性,我直接使用下面代码就行了(没有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)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227885.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:18
下一篇 2026年3月16日 下午8:18


相关推荐

  • 使用FFMpeg 提取MKV文件中的字幕

    使用FFMpeg 提取MKV文件中的字幕MKV 封装格式是万能封装格式 可以封装几乎所有的视频和音频编码格式 可以包含多个视频流 音频流和字幕流 本文将介绍使用 FFMpeg 解码视频文件 提去字幕内容并保存 这里仅提取 ASS 格式的字幕文件 使用 FFMpeg 解 MKV 封装 获取字幕流信息 voidFFMpegAs openVideoFil QStringfileN 打开视频文件 i

    2026年3月19日
    1
  • Go开发利器Cursor:插件安装+调试配置一站式教程

    Go开发利器Cursor:插件安装+调试配置一站式教程

    2026年3月15日
    3
  • 短信验证码的作用及安全性

    短信验证码的作用及安全性在每个人都可以参与编辑的Web2.0时代,人人都在使用和注册各种APP账号,而验证码短信就是必不可少的认证工具!所以,验证码短信逐步占据了短信行业中的重要份额。而短信验证码的作用是:1、作为身份凭证首先,验证码是商家给用户验证身份的一个凭证,通过手机短信发送验证码,是最普遍、最安全验证用户真实身份的方式。短信验证码广泛应用于用户注册、密码找回、登陆保护、身份认证、随机密码、交易确认等应用场景。2、…

    2022年7月14日
    24
  • pycharm如何调整字体大小

    pycharm如何调整字体大小关于 pycharm 如何调整字体大小的问题解决方案 1 打开 PyCharm 单击 File 2 选择 Settings 会打开一个弹窗 3 接着选中弹窗中的 Editor 4 然后 选中 Font 5 然后我们可以看到如图所示的界面 其中红方框里面是显示效果 6 如图 改变红方框标注的 Size 值的大小 就可以调节字体大小了 该篇文章图片及文本全部摘自百度经验 仅供学习参考

    2026年3月27日
    3
  • plt.annotate()函数解析(最清晰的解释)

    plt.annotate()函数解析(最清晰的解释)plt annotate 函数用于标注文字 plt annotate s str xy x y xytext l1 l2 参数 s 为注释文本内容 xy 为被注释的坐标点 xytext 为注释文字的坐标位置 xycoords 参数如下 figurepoints 图左下角的点 figurepixels 图左下角的像素 figur

    2026年3月17日
    2
  • TinyXML介绍「建议收藏」

    TinyXML介绍「建议收藏」http://www.cnblogs.com/phinecos/archive/2008/03/11/1100912.html读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好。TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Wind

    2022年5月3日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号