FastJson对复杂的泛型对象的解析问题

2024-06-11 05:48

本文主要是介绍FastJson对复杂的泛型对象的解析问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先要说的是FastJson提供了一个用于处理泛型反序列化的类TypeReference,在知道具体泛型类型的情况下可以实现反序列化,这里由于应用场景不适用不对其进行讨论。

如下场景:

public class PieChartVO<T extends BaseDebtVO> implements Serializable {private static final long serialVersionUID = -6422895776727574355L;private BigDecimal avgYearRate;private ArrayList<T> transVOs;public BigDecimal getAvgYearRate() {return avgYearRate;}public void setAvgYearRate(BigDecimal avgYearRate) {this.avgYearRate = avgYearRate;}public ArrayList<T> getTransVOs() {return transVOs;}public void setTransVOs(ArrayList<T> transVOs) {this.transVOs = transVOs;}
}
public class CreditorDebtVO extends BaseDebtVO {private static final long serialVersionUID = -254172337494852158L;private BigDecimal totalEarning;public BigDecimal getTotalEarning() {return totalEarning;}public void setTotalEarning(BigDecimal totalEarning) {this.totalEarning = totalEarning;}}
public class ObligorDebtVO extends BaseDebtVO {private static final long serialVersionUID = 3314361571700869005L;private Integer overdueCount;private BigDecimal overdueOtherFee;public Integer getOverdueCount() {return overdueCount;}public void setOverdueCount(Integer overdueCount) {this.overdueCount = overdueCount;}public BigDecimal getOverdueOtherFee() {return overdueOtherFee;}public void setOverdueOtherFee(BigDecimal overdueOtherFee) {this.overdueOtherFee = overdueOtherFee;}
}

{"body": {"avgYearRate": 14.8, "transVOs": [{"avgRate": 19.2, "cleanCount": 8, "id": 15, "subTitle": "aaa", "title": "bbb", "totalEarning": 20.75, "totalPrincipal": 17000, "transCount": 3, "transMoney": 4698.93, "transOverdueMoney": 0}]}, "result": 1
}

对于获取到的json数据并不知道具体的泛型类型,也就没法指定的情况下,解决方案是对反序列化进行自定义定制,fastJson自身对基础的field内置了许多反序列化器,当对json反序列化时,会根据filed的class找到相应的反序列化器来执行反序列化。

public class ParserConfig {private final IdentityHashMap<Type, ObjectDeserializer> deserializers = new IdentityHashMap<Type, ObjectDeserializer>();/**省略了其他代码*/private void initDeserializers() {deserializers.put(SimpleDateFormat.class, MiscCodec.instance);deserializers.put(java.sql.Timestamp.class, SqlDateDeserializer.instance_timestamp);deserializers.put(java.sql.Date.class, SqlDateDeserializer.instance);deserializers.put(java.sql.Time.class, TimeDeserializer.instance);deserializers.put(java.util.Date.class, DateCodec.instance);deserializers.put(Calendar.class, CalendarCodec.instance);deserializers.put(XMLGregorianCalendar.class, CalendarCodec.instance);deserializers.put(JSONObject.class, MapDeserializer.instance);deserializers.put(JSONArray.class, CollectionCodec.instance);deserializers.put(Map.class, MapDeserializer.instance);deserializers.put(HashMap.class, MapDeserializer.instance);deserializers.put(LinkedHashMap.class, MapDeserializer.instance);deserializers.put(TreeMap.class, MapDeserializer.instance);deserializers.put(ConcurrentMap.class, MapDeserializer.instance);deserializers.put(ConcurrentHashMap.class, MapDeserializer.instance);deserializers.put(Collection.class, CollectionCodec.instance);deserializers.put(List.class, CollectionCodec.instance);deserializers.put(ArrayList.class, CollectionCodec.instance);deserializers.put(Object.class, JavaObjectDeserializer.instance);deserializers.put(String.class, StringCodec.instance);deserializers.put(StringBuffer.class, StringCodec.instance);deserializers.put(StringBuilder.class, StringCodec.instance);deserializers.put(char.class, CharacterCodec.instance);deserializers.put(Character.class, CharacterCodec.instance);deserializers.put(byte.class, NumberDeserializer.instance);deserializers.put(Byte.class, NumberDeserializer.instance);deserializers.put(short.class, NumberDeserializer.instance);deserializers.put(Short.class, NumberDeserializer.instance);deserializers.put(int.class, IntegerCodec.instance);deserializers.put(Integer.class, IntegerCodec.instance);deserializers.put(long.class, LongCodec.instance);deserializers.put(Long.class, LongCodec.instance);deserializers.put(BigInteger.class, BigIntegerCodec.instance);deserializers.put(BigDecimal.class, BigDecimalCodec.instance);deserializers.put(float.class, FloatCodec.instance);deserializers.put(Float.class, FloatCodec.instance);deserializers.put(double.class, NumberDeserializer.instance);deserializers.put(Double.class, NumberDeserializer.instance);deserializers.put(boolean.class, BooleanCodec.instance);deserializers.put(Boolean.class, BooleanCodec.instance);deserializers.put(Class.class, MiscCodec.instance);deserializers.put(char[].class, new CharArrayCodec());deserializers.put(AtomicBoolean.class, BooleanCodec.instance);deserializers.put(AtomicInteger.class, IntegerCodec.instance);deserializers.put(AtomicLong.class, LongCodec.instance);deserializers.put(AtomicReference.class, ReferenceCodec.instance);deserializers.put(WeakReference.class, ReferenceCodec.instance);deserializers.put(SoftReference.class, ReferenceCodec.instance);deserializers.put(UUID.class, MiscCodec.instance);deserializers.put(TimeZone.class, MiscCodec.instance);deserializers.put(Locale.class, MiscCodec.instance);deserializers.put(Currency.class, MiscCodec.instance);deserializers.put(InetAddress.class, MiscCodec.instance);deserializers.put(Inet4Address.class, MiscCodec.instance);deserializers.put(Inet6Address.class, MiscCodec.instance);deserializers.put(InetSocketAddress.class, MiscCodec.instance);deserializers.put(File.class, MiscCodec.instance);deserializers.put(URI.class, MiscCodec.instance);deserializers.put(URL.class, MiscCodec.instance);deserializers.put(Pattern.class, MiscCodec.instance);deserializers.put(Charset.class, MiscCodec.instance);deserializers.put(JSONPath.class, MiscCodec.instance);deserializers.put(Number.class, NumberDeserializer.instance);deserializers.put(AtomicIntegerArray.class, AtomicCodec.instance);deserializers.put(AtomicLongArray.class, AtomicCodec.instance);deserializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance);deserializers.put(Serializable.class, JavaObjectDeserializer.instance);deserializers.put(Cloneable.class, JavaObjectDeserializer.instance);deserializers.put(Comparable.class, JavaObjectDeserializer.instance);deserializers.put(Closeable.class, JavaObjectDeserializer.instance);deserializers.put(JSONPObject.class, new JSONPDeserializer());}public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {/** 首先从内部已经注册查找特定type的反序列化实例 */ObjectDeserializer derializer = deserializers.get(type);if (derializer != null) {return derializer;}.......}}

可以看到对于ArrayList的默认的反序列化器是CollectionCodec,另外fastjson还提供了@JSONField注解对field可以有一些自定义的处理,其deserializeUsing属性可以指定具体的反序列化器。我们要做的就很简单了。

自定义反序列化器实现CollectionCodec,具体的反序列化工作仍然交由CollectionCodec处理,只不过须要对得到的对象进行自定义的加工。这里通过判断某个field是否存在来决定以哪个类来反序列化。

public class DebtVODeserializer extends CollectionCodec {@Overridepublic <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {T list = super.deserialze(parser, type, fieldName);JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(list));ArrayList<CreditorDebtVO> debtVOs = new ArrayList<>();if (jsonArray != null && jsonArray.size()>0){if (jsonArray.getJSONObject(0).get("totalEarning")!=null){ArrayList<CreditorDebtVO> creditorDebtVOList = (ArrayList<CreditorDebtVO>)JSON.parseArray(JSON.toJSONString(list),CreditorDebtVO.class);return (T)creditorDebtVOList;} else if (jsonArray.getJSONObject(0).get("overdueOtherFee")!=null){ArrayList<ObligorDebtVO> obligorDebtVOList = (ArrayList<ObligorDebtVO>)JSON.parseArray(JSON.toJSONString(list),ObligorDebtVO.class);return (T)obligorDebtVOList;}} else {return list;}return (T)debtVOs;}
}

修改PieChartVO,指定自定义的反序列化器

@JSONField(deserializeUsing = DebtVODeserializer.class)public void setTransVOs(ArrayList<T> transVOs) {this.transVOs = transVOs;}

PieChartVO vo = JSON.parseObject(json,PieChartVO.class);

如上,直接反序列化即可,对于使用方而言,不需要判断用哪个类来反序列化,代码上看简洁了许多...

这篇关于FastJson对复杂的泛型对象的解析问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1050348

相关文章

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

IDEA和GIT关于文件中LF和CRLF问题及解决

《IDEA和GIT关于文件中LF和CRLF问题及解决》文章总结:因IDEA默认使用CRLF换行符导致Shell脚本在Linux运行报错,需在编辑器和Git中统一为LF,通过调整Git的core.aut... 目录问题描述问题思考解决过程总结问题描述项目软件安装shell脚本上git仓库管理,但拉取后,上l

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

idea npm install很慢问题及解决(nodejs)

《ideanpminstall很慢问题及解决(nodejs)》npm安装速度慢可通过配置国内镜像源(如淘宝)、清理缓存及切换工具解决,建议设置全局镜像(npmconfigsetregistryht... 目录idea npm install很慢(nodejs)配置国内镜像源清理缓存总结idea npm in