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 {
    @Override
    public <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);

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值