关于java:FastJson-序列化出现ref问题

在用FastJson对对象进行序列化时,发现进去的json字符串中始终存在”$ref”,具体示例如下:

public String buildRiskQueryLogFastJson(BaseContext baseContext, Map<String, Map<String, String>> riskRejectMap) {
        List<RiskQueryLogDO> riskQueryLogDOList = new ArrayList<>();
        HashMap<String, String> dimensionMap = new HashMap<>(baseContext.getDimensionInfoMap());
        for (String uniqueKey : baseContext.getUniqueKeyList()) {
            RiskQueryLogDO riskQueryLogDO = new RiskQueryLogDO();
            riskQueryLogDO.setQueryType(baseContext.getQueryType());
            riskQueryLogDO.setRiskCheckId(baseContext.getRiskCheckId());
            riskQueryLogDO.setBizLine(baseContext.getBizLine());
            riskQueryLogDO.setEventId(baseContext.getEventId());
            riskQueryLogDO.setChannel(baseContext.getChannel());
            riskQueryLogDO.setOrigin(baseContext.getOrigin());
            riskQueryLogDO.setUniqueKey(uniqueKey);
            if (riskRejectMap.containsKey(uniqueKey)) {
                riskQueryLogDO.setRiskResult(DecisionCodeEnum.getFromName(riskRejectMap.get(uniqueKey).get(ContextKeyConstant.RISK_RESULT)).getCode());
            } else {
                riskQueryLogDO.setRiskResult(DecisionCodeEnum.PASS.getCode());
            }
            riskQueryLogDO.setDimensionData(dimensionMap);
            riskQueryLogDOList.add(riskQueryLogDO);
        }
        Map<String, List<RiskQueryLogDO>> msgMap = new HashMap<>();
        msgMap.put("data", riskQueryLogDOList);
        return JSON.toJSONString(msgMap);
    }
@Test
    public void sendMessageTest(){

        BaseContext baseContext = new BaseContext();
        Map<String, String> dimensionInfoMap = new HashMap<>();
        dimensionInfoMap.put(ContextKeyConstant.USER_ID, "110119120");
        dimensionInfoMap.put(ContextKeyConstant.USER_TYPE, "2");
        dimensionInfoMap.put(ContextKeyConstant.USER_ID_TYPE, "1");
        List<Map<String, String>> contextInfoMapList = new ArrayList<>();
        List<String> uniqueKeyList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Map<String, String> infoMap = new HashMap<>();
            infoMap.put(ContextKeyConstant.ACTIVITY_CATEGORY, "2");
            infoMap.put(ContextKeyConstant.ACTIVITY_TYPE_ID, String.valueOf(new Random().nextInt(10)));
            infoMap.put(ContextKeyConstant.ASSUME_TYPE, String.valueOf(new Random().nextInt(2)));
            infoMap.put(ContextKeyConstant.ACTIVITY_ID, String.valueOf(i));
            infoMap.put(ContextKeyConstant.APPLY_ID, String.valueOf(i));
            infoMap.put(ContextKeyConstant.UNIQUE_KEY, String.valueOf(i));
            contextInfoMapList.add(infoMap);
            uniqueKeyList.add(String.valueOf(i));
        }
        baseContext.setQueryType(QueryTypeEnum.BATCH_AGGREGATION.getCode());
        baseContext.setRiskCheckId(String.valueOf(new Random(100).nextInt()));
        baseContext.setBizLine(1);
        baseContext.setEventId(1);
        baseContext.setChannel(1);
        baseContext.setOrigin(1);
        baseContext.setDimensionInfoMap(dimensionInfoMap);
        baseContext.setContextInfoMapList(contextInfoMapList);
        baseContext.setUniqueKeyList(uniqueKeyList);

        Map<String, Map<String, String>> riskRejectMap = new HashMap<>();
        Map<String, String> infoResultMap = new HashMap<>();
        infoResultMap.put(ContextKeyConstant.RISK_RESULT, DecisionCodeEnum.REJECT.getName());
        infoResultMap.put(ContextKeyConstant.ACTIVITY_CATEGORY, "2");
        infoResultMap.put(ContextKeyConstant.ACTIVITY_TYPE_ID, "1");
        infoResultMap.put(ContextKeyConstant.ACTIVITY_ID, "1");
        infoResultMap.put(ContextKeyConstant.APPLY_ID, "1");
        infoResultMap.put(ContextKeyConstant.ASSUME_TYPE, "1");
        for (int i = 0; i < 30; i++) {
            riskRejectMap.put(String.valueOf(i), infoResultMap);
        }
        //riskQueryLogProducer.sendMessage(baseContext, riskRejectMap);
        System.out.println(riskQueryLogProducer.buildRiskQueryLogFastJson(baseContext, riskRejectMap));
    }

后果是这样的:

能够看到,对于一个对象,当其首次呈现时,FastJson的序列化是失常工作的,然而当其反复呈现时,就会序列化实现,变为对象的援用.能够想到,这肯定是FastJson外部存在一些非凡逻辑,问题产生的起因在于FastJson存在循环/反复援用检测个性,并且该个性是缺省开启的。
实体转化为json字符串后呈现了$ref字样的货色,这是因为在传输的数据中呈现雷同的对象时,fastjson默认开启援用检测将雷同的对象写成援用的模式,援用是通过”$ref”来示意的。

援用 形容
“$ref”:”..” 上一级
“$ref”:”@” 以后对象,也就是自援用
“$ref”:”$” 根对象
“$ref”:”$.children.0″ 基于门路的援用,相当于 root.getChildren().get(0)

想要解决这个问题,非常简单,只须要将原来的menujson.toJSONString()改为如下代码:

JSON.toJSONString(msgMap, SerializerFeature.DisableCircularReferenceDetect);

如果想要全局敞开该性能:

JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();

FastJson要这个个性干吗用?
fastjson默认对json序列化的时候进行循环援用的检测,从而防止了呈现StackOverFlow异样。当序列化后的JSON传输到浏览器或者其余语言中,这些json解析器不反对循环援用,从而导致数据失落。
疑难: 既然在很多场景下浏览器并不反对该性能,那么为甚么还要把这个性能设置为缺省开启呢?
起因在于,如果存在循环援用,很有可能会呈现SOF异样,因而设计了循环援用检测的爱护

reference
https://juejin.cn/post/684490…
https://blog.csdn.net/fly9109…

评论

发表回复

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

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理