FastJson对Object对象的解析问题

本文介绍了解决FastJson在解析包含泛型的复杂对象时遇到的问题,通过自定义反序列化器ActivitiyRuleVoDeserializer,成功实现了ActivityRuleList中不同类型子类实例的正确解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

ActivityRuleBase 基础类,ActivityRuleUserVo,ActivityRulePayTypeVo 继承ActivityRuleBase 类

public class Activity implements Serializable {

	private Long id;  //
	private String name;  //活动名称
	private List<Object> ActivityRuleList;//实际可能是多个不同类实例,eg:cRule,dRule
//setting,getting
}

Activity 数据json字符串解析成对象实例数据时,如下是无法实现的,即便是加上了TypeReference子类的特有数据仍然会丢失

Activity sv2 = JSON.parseObject(text, Activity.class);
        System.out.println(JSON.toJSONString(sv2));
[{"condition":"11111","ruleType":"USER_RULE"},{"payType":"22222","ruleType":"PAY_TYPE_RULE"}]
USER_RULE={"condition":"11111","ruleType":"USER_RULE"}
PAY_TYPE_RULE={"payType":"22222","ruleType":"PAY_TYPE_RULE"}
json解析结果----------------------------------------------------
{"activityRuleList":[{"condition":"11111","ruleType":"USER_RULE"},{"payType":"22222","ruleType":"PAY_TYPE_RULE"}],"name":"ces","status":1}
USER_RULE={"ruleType":"USER_RULE"}
PAY_TYPE_RULE={"ruleType":"PAY_TYPE_RULE"}
{"activityRuleList":[{"ruleType":"USER_RULE"},{"ruleType":"PAY_TYPE_RULE"}],"name":"ces","status":1}

看解析的结果,子类的自有属性值并没有解析处来,只有父类的属性值。

解决办法

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

public class ActivitiyRuleVoDeserializer 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<ActivityRuleBase> debtVOs = new ArrayList<>();

        for(int i=0;i<jsonArray.size();i++){
            // 遍历 jsonarray 数组,把每一个对象转成 json 对象
            JSONObject jsob = jsonArray.getJSONObject(i);
            // 得到 每个对象中的属性值
            System.out.println(jsob.get("ruleType")+"="+JSON.toJSONString(jsob)) ;

            switch (RuleType.valueOf(jsob.get("ruleType").toString())) {
                case USER_RULE://USER_RULE 用户限制规则
                    ActivityRuleUserVo activityRuleUser = JSON.parseObject(JSON.toJSONString(jsob),ActivityRuleUserVo.class);
                    debtVOs.add(activityRuleUser);
                    break;
                case PAY_TYPE_RULE://PAY_TYPE_RULE支付方式
                    ActivityRulePayTypeVo activityRulePayProm = JSON.parseObject(JSON.toJSONString(jsob),ActivityRulePayTypeVo.class);
                    debtVOs.add(activityRulePayProm);
                    break;
                case DISCOUNT_RULE://打折活动
                    ActivityRuleDiscountVo activityRuleDiscount = JSON.parseObject(JSON.toJSONString(jsob),ActivityRuleDiscountVo.class);
                    debtVOs.add(activityRuleDiscount);
                    break;
            	// 其他活动规则省略
                default:
                    ActivityRuleBase activityRuleBase  = JSON.parseObject(JSON.toJSONString(jsob),ActivityRuleBase.class);
                    debtVOs.add(activityRuleBase);
            }


        }



   /*     if (jsonArray != null && jsonArray.size()>0){

            for (:
            jsonArray) {

            }


            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;
    }
}

在要解析的类的setting方法上加上如下注解

 @JSONField(deserializeUsing = ActivitiyRuleVoDeserializer.class)
    public void setActivityRuleList(List<Object> activityRuleList) {
        ActivityRuleList = activityRuleList;
    }

测试方法

   public static void main(String[] args) {

        ActivityVo sv = new ActivityVo();
        sv.setStatus(1).setName("ces");
        List<ActivityRuleBase> activityRuleList = Lists.newArrayList();//实际可能是多个


        ActivityRuleUser activityRuleUser1 = new ActivityRuleUser();
        activityRuleUser1.setRuleType("USER_RULE");
        activityRuleUser1.setCondition("11111");

        ActivityRulePayType activityRulePayProm1 = new ActivityRulePayType();
        activityRulePayProm1.setRuleType("PAY_TYPE_RULE");
        activityRulePayProm1.setPayType("22222");


        activityRuleList.add(activityRuleUser1);
        activityRuleList.add(activityRulePayProm1);

        sv.setActivityRuleList(activityRuleList);

        ParserConfig parserConfig = new ParserConfig() {
            @Override
            public ObjectDeserializer getDeserializer(Type type) {
                if (type == ActivityRuleUser.class) {
                    return super.getDeserializer(ActivityRuleUser.class);
                }
                return super.getDeserializer(type);
            }
        };


        String text1 = JSON.toJSONString(activityRuleList);
        System.out.println(text1);

        JSONArray jsonArray = JSON.parseArray(text1);

        for(int i=0;i<jsonArray.size();i++){
            // 遍历 jsonarray 数组,把每一个对象转成 json 对象
            JSONObject jsob = jsonArray.getJSONObject(i);
            // 得到 每个对象中的属性值
            System.out.println(jsob.get("ruleType")+"="+JSON.toJSONString(jsob)) ;
        }
        System.out.println("json解析结果----------------------------------------------------") ;


        String text = JSON.toJSONString(sv);
        System.out.println(text);

        Activity sv2 = JSON.parseObject(text, Activity.class);
        System.out.println(JSON.toJSONString(sv2));


    }

打印出来的数据

[{"condition":"11111","ruleType":"USER_RULE"},{"payType":"22222","ruleType":"PAY_TYPE_RULE"}]
USER_RULE={"condition":"11111","ruleType":"USER_RULE"}
PAY_TYPE_RULE={"payType":"22222","ruleType":"PAY_TYPE_RULE"}
json解析结果----------------------------------------------------
{"activityRuleList":[{"condition":"11111","ruleType":"USER_RULE"},{"payType":"22222","ruleType":"PAY_TYPE_RULE"}],"name":"ces","status":1}
USER_RULE={"condition":"11111","ruleType":"USER_RULE"}
PAY_TYPE_RULE={"payType":"22222","ruleType":"PAY_TYPE_RULE"}
{"activityRuleList":[{"condition":"11111","ruleType":"USER_RULE","toAllUser":false},{"payType":"22222","ruleType":"PAY_TYPE_RULE"}],"name":"ces","status":1}

参考资料

FastJson对泛型解析问题
https://blog.youkuaiyun.com/u011535541/article/details/80492091
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>好的,我现在需要帮助用户解决如何用FastJSON(用户可能指的是Fastjson,但误写为fast2)来解析非常大的JSON字符串为Java对象问题。首先,我得确认用户的需求,他们有一个超长的JSON字符串,可能因为内存限制,无法一次性加载到内存中。这时候,常规的解析方法可能不适用,需要流式解析或者分块处理。 首先,用户提到的“fast2”可能是Fastjson的笔误,因为Fastjson是阿里巴巴的开源库,版本2.x可能存在,但需要确认。不过根据引用[2]和[3]中的内容,用户之前接触过Fastjson的方法,比如JSONObject.parseObject和JSONArray.parseArray。所以假设用户是想使用Fastjson来处理大JSON文件。 接下来,我需要回忆Fastjson是否支持流式解析。记得Fastjson提供了JSONReader类,可以用于流式解析,这样可以逐部分读取JSON内容,减少内存占用。同时,用户可能需要了解如何分块读取文件,比如使用Java的BufferedReader逐行读取或者按块读取,然后结合流式解析器处理。 然后,考虑到大文件处理的关键点:避免一次性加载整个文件到内存。因此,解决方案应该分步骤:使用文件流逐块读取,配合Fastjson的JSONReader来逐步解析。这样,每次处理一部分数据,转换成Java对象后释放内存。 另外,用户可能需要处理的是数组结构的JSON,比如一个包含大量对象的数组。这时候,JSONReader可以逐个读取数组中的对象,每读取一个就进行处理,而不需要等待整个数组加载完毕。 还要注意异常处理,比如在解析过程中遇到格式错误时如何处理,以及资源释放,确保文件流正确关闭,避免资源泄漏。 然后,根据引用[3]中的例子,用户可能已经知道如何将JSON数组转换为Java对象列表,但问题在于当数据量太大时,内存不足。所以需要将原来的JSONArray.parseArray方法替换为流式解析。 最后,总结步骤:使用IO流逐块读取文件,创建JSONReader实例,逐步解析JSON内容,处理每个对象,及时释放资源。同时,可能需要提供代码示例,展示如何具体实现这一过程,并提醒相关的注意事项,比如处理大文件时的性能优化和错误处理。</think>要使用Fastjson解析非常大的JSON字符串为Java对象,可以通过流式解析(Stream API)和分块读取的方式处理,避免一次性加载整个文件到内存。以下是具体实现步骤: ### 1. 流式解析(JSONReader) Fastjson的`JSONReader`支持按需解析,逐层读取JSON内容。适用于处理数组或嵌套结构的JSON数据。 ```java import com.alibaba.fastjson.JSONReader; import java.io.FileReader; public void parseLargeJson(String filePath) { try (FileReader fileReader = new FileReader(filePath); JSONReader jsonReader = new JSONReader(fileReader)) { jsonReader.startArray(); // 假设JSON最外层是数组 while (jsonReader.hasNext()) { // 逐条解析数组中的对象 YourObject obj = jsonReader.readObject(YourObject.class); process(obj); // 自定义处理逻辑 } jsonReader.endArray(); } catch (Exception e) { e.printStackTrace(); } } ``` ### 2. 分块读取 + 局部解析 对于非结构化数据,可通过`BufferedReader`分块读取并手动拼接有效片段: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.io.BufferedReader; import java.io.FileReader; public void parseByChunks(String filePath) { try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { StringBuilder buffer = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { buffer.append(line); if (isCompleteJson(buffer.toString())) { // 自定义判断是否构成完整JSON JSONObject obj = JSON.parseObject(buffer.toString()); process(obj); buffer.setLength(0); // 清空缓冲区 } } } catch (Exception e) { e.printStackTrace(); } } ``` ### 关键点说明 - **流式解析**:适合处理数组或嵌套层级明确的JSON,减少内存占用[^2]。 - **分块读取**:需根据业务逻辑判断数据完整性(如依赖括号匹配)。 - **对象映射**:使用`readObject(Class)`可直接转换为目标Java类[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值