fastjson迁移jackson之解析‘$ref‘

fastjson迁移jackson

性能比较

这是我自己用jmh测试的记录
序列化

对象数量hutoolfastjsonjackson
1000.17s0.17s0.52s
10000.32s0.22s0.59s
100001.73s0.61s0.68s
1000006.30s1.16s0.91s
20000010.95s1.76s1.26s

反序列化

对象数量hutoolfastjsonjackson
1000.18s0.29s0.57s
10000.41s0.26s0.64s
100001.84s0.46s0.68s
1000006.22s1.23s1.24s
20000012.83s2.57s1.83s

可见数据量上去后,fastjson和jackson差距不大

迁移遇到的bug

默认情况下,fastjson会启用jsonpath来解决循环依赖。可以使用SerializerFeature.DisableCircularReferenceDetect来关闭此选项,但不推荐。但输出的带$ref的json不能直接用jackson读取。所以自己封装了一个Moudle:

import com.alibaba.fastjson.JSONPath;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Objects;

/**
 * @Date : 2022/7/30
 * @Description : 兼容fastjson->jackson 迁移时$ref的path问题
 */
public class BeanRefMoudle extends Module {

    @Override
    public String getModuleName() {
        return "beanRefMoudle";
    }


    @Override
    public Version version() {
        return Version.unknownVersion();
    }


    @Override
    public void setupModule(SetupContext context) {
        context.addBeanDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                if (deserializer instanceof BeanDeserializer) {
                    return new BeanRefDeserializer((BeanDeserializer) deserializer);
                }
                return deserializer;
            }
        });
    }


}

@Slf4j
class BeanRefDeserializer extends BeanDeserializer {

    private static final String REF="$ref";

    public BeanRefDeserializer(BeanDeserializer src) {
        super(src);
    }

    private static Object getSecondRootValue(JsonStreamContext pctx) {
        if (Objects.isNull(pctx)) {
            return null;
        }
        JsonStreamContext real;
        do {
            real = pctx;
            pctx = pctx.getParent();
        } while (!pctx.inRoot());
        return real.getCurrentValue();
    }

    @Override
    public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException {
        if(Objects.equals(REF,p.getCurrentName())){
            return match$ref(p);
        }
        return super.deserializeFromObject(p, ctxt);
    }

    private Object match$ref(JsonParser p) throws IOException {
        p.nextToken();
        try {
            String ref=p.getValueAsString();
            JsonStreamContext pctx = p.getParsingContext();
            return JSONPath.eval(getSecondRootValue(pctx), ref);
        } catch (Exception e) {
            log.error("jackson解析{}异常",REF,e);
            return null;
        }finally {
            p.nextToken();
        }
    }
}

再注册Moudle到SPI
resource文件夹下新建META-INF文件夹,META-INF文件夹下新建services文件夹,services文件夹下新建com.fasterxml.jackson.databind.Module文件,文件内容为你的模块全类名(com.xxx.xxxx.framework.json.BeanRefMoudle)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Fastjson是一个Java语言编写的高性能JSON处理器,而Jackson也是一个Java语言编写的JSON处理器,不过它还支持XML、YAML和其他数据格式。Fastjson的性能比Jackson更高效,但是Jackson有更好的编程接口和更多的社区支持。 ### 回答2: fastjsonJackson都是Java中常用的JSON处理库,用于将Java对象与JSON数据进行相互转换。它们有以下几个区别: 1. 性能:fastjson在性能方面相对较强,通常比Jackson更快。这是因为fastjson采用了一些优化策略,如缓存、预热和ASM字节码生成等。而Jackson则相对较慢,但它提供了更多的功能和可自定义的选项。 2. 依赖和体积:fastjson是一个单独的JAR包,不依赖于其他类库,体积相对较小。而Jackson则是一个更庞大的生态系统,由多个JAR包组成,其中可能会依赖于其他类库,因此体积相对较大。 3. 功能和灵活性:Jackson提供了更多的功能和选项,可以更细粒度地控制JSON的生成和解析过程。它支持XML和JSON之间的转换,并提供了一些高级特性,如多态类型处理、数据绑定等。相比之下,fastjson在一些高级功能方面可能相对简单,并且配置选项较少。 4. 社区支持和文档:Jackson有着更广泛的社区支持,有更多的用户和开发者参与,因此它的文档和例子更丰富。同时,Jackson也是Spring框架的默认JSON处理库,因此在Spring项目中使用更加方便。 综上所述,fastjsonJackson都是功能强大的JSON处理库,选择使用哪个取决于具体项目需求和性能要求。如果对性能要求较高,可以选择fastjson;如果需要更多的功能和灵活性,以及更广泛的社区支持,可以选择Jackson

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值