用了几年的 Fastjson,我最终替换成了Jackson!

本文详细剖析了fastjson在执行反序列化和序列化过程中的特性控制,包括`parseObject`和`toJSONString`方法的参数分析,以及`Feature`和`SerializerFeature`的作用。作者还比较了fastjson与Jackson在注解和特性方面的异同。
摘要由CSDN通过智能技术生成

从方法入参就能猜到,fastjson在执行反序列化时的Parse行为由com.alibaba.fastjson.parser.Feature指定。研究parseObject的源码后,发现底层最终都是使用的以下方法:

public static  T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature… features) {

if (input == null) {

return null;

}

// featureValues作为基准解析特性开关值

// 入参features和featureValues取并集得到最终的解析特性

if (features != null) {

for (Feature feature : features) {

featureValues |= feature.mask;

}

}

DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);

if (processor != null) {

if (processor instanceof ExtraTypeProvider) {

parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);

}

if (processor instanceof ExtraProcessor) {

parser.getExtraProcessors().add((ExtraProcessor) processor);

}

if (processor instanceof FieldTypeResolver) {

parser.setFieldTypeResolver((FieldTypeResolver) processor);

}

}

T value = (T) parser.parseObject(clazz, null);

parser.handleResovleTask(value);

parser.close();

return (T) value;

}

通过IDE搜索usage后,发现当没有作为基准解析特性开关的featureValues入参时,都是使用的DEFAULT_PARSE_FEATURE作为基准解析特性开关,以下是JSON.DEFAULT_PARSE_FEATURE的实例化代码:

static {

int features = 0;

features |= Feature.AutoCloseSource.getMask();

features |= Feature.InternFieldNames.getMask();

features |= Feature.UseBigDecimal.getMask();

features |= Feature.AllowUnQuotedFieldNames.getMask();

features |= Feature.AllowSingleQuotes.getMask();

features |= Feature.AllowArbitraryCommas.getMask();

features |= Feature.SortFeidFastMatch.getMask();

features |= Feature.IgnoreNotMatch.getMask();

DEFAULT_PARSER_FEATURE = features;

}

fastjson还会从环境变量中读取配置来修改DEFAULT_PARSER_FEATURE(虽然很少会有人这么做),但最好还是通过实际运行一下程序来确认你的环境中的实际解析特性开关。

@Test

public void printFastJsonDefaultParserFeature() {

for (Feature feature : Feature.values()) {

if (Feature.isEnabled(JSON.DEFAULT_PARSER_FEATURE, feature)) {

System.out.println(feature);

}

}

}

fastjson 和 jackson的反序列化特性对照表

反序列化fastjson和jackson的特性TestCase见DeserializationUseJacksonReplaceFastJsonTest.java

Serialization


fastjson将Java Bean序列化成json字符串通常也是使用com.alibaba.fastjson.JSON的静态方法(JSONObjectJSONArray的静态方法也是来自于JSON),常用的有以下几个API:

public static String toJSONString(Object object);

public static String toJSONString(Object object, SerializerFeature… features);

public static String toJSONStringWithDateFormat(Object object, String dateFormat, SerializerFeature… features);

public static String toJSONString(Object object, boolean prettyFormat);

public static void writeJSONString(Writer writer, Object object, SerializerFeature… features);

从方法入参也能看出,在序列化时,fastjson的特性由SerializerFeature控制,研究toJSONString的源码后,发现最终都会调用以下方法:

public static String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters, String dateFormat, int defaultFeatures, SerializerFeature… features) {

SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);

try {

JSONSerializer serializer = new JSONSerializer(out, config);

if (dateFormat != null && dateFormat.length() != 0) {

serializer.setDateFormat(dateFormat);

serializer.config(SerializerFeature.WriteDateUseDateFormat, true);

}

if (filters != null) {

for (SerializeFilter filter : filters) {

serializer.addFilter(filter);

}

}

serializer.write(object);

return out.toString();

} finally {

out.close();

}

}

通过IDE搜索usage后,发现当没有作为基准解析特性开关的defaultFeatures入参时,都是使用的DEFAULT_GENERATE_FEATURE作为基准解析特性开关,以下是JSON.DEFAULT_GENERATE_FEATURE的实例化代码:

static {

int features = 0;

features |= SerializerFeature.QuoteFieldNames.getMask();

features |= SerializerFeature.SkipTransientField.getMask();

features |= SerializerFeature.WriteEnumUsingName.getMask();

features |= SerializerFeature.SortField.getMask();

DEFAULT_GENERATE_FEATURE = features;

config(IOUtils.DEFAULT_PROPERTIES);

}

fastjson还会从环境变量中读取配置来修改DEFAULT_GENERATE_FEATURE(虽然很少会有人这么做),但最好还是通过实际运行一下程序来确认你的环境中的实际解析特性开关。

@Test

public void printFastJsonDefaultGenerateFeature() {

for (SerializerFeature feature : SerializerFeature.values()) {

if (SerializerFeature.isEnabled(JSON.DEFAULT_GENERATE_FEATURE, feature)) {

System.out.println(feature);

}

}

}

fastjson 和 jackson的序列化特性对照表

序列化fastjson和jackson的特性TestCase见SerializationUseJacksonReplaceFastJsonTest.java

Annotation


fastjsonzhu相对于jackson来说注解的功能划分的并没有那么细,因此fastjson的一个注解可能等价于jackson多个注解的组合。

@JSONPOJOBuilder

指定反序列化时创建java对象使用的build方法,对应jackson的@JsonPOJOBuilder

@JSONCreator

指定反序列化时创建java对象使用的构造方法,对应jackson的@JsonCreator

@JSONField

指定序列化和反序列化field时的行为。反序列化时,等价于@JsonProperty + @JsonDeserialize + @JsonUnwrapped + @JsonFormat@JsonAlias

序列化时,等价于@JsonProperty + @JsonSerialize + @JsonUnwrapped + @JsonFormat + @JsonRawValue + @JsonView

@Retention(RetentionPolicy.RUNTIME)

@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })

public @interface JSONField {

// 序列化和反序列化时的字段顺序,等价于jackson的@JsonProperty.index()

int ordinal() default 0;

// 序列化和反序列化时的字段名称映射,等价于jackson的@JsonProperty.value()

String name() default “”;

// 序列化和反序列化时的数据格式(日期格式、16进制等等),等价于jackson的@JsonFormat.shape() + @JsonFormat.pattern()

String format() default “”;

// 字段是否序列化,等价于jackson的@JsonProperty.access()

boolean serialize() default true;

// 字段是否反序列化,等价于jackson的@JsonProperty.access()

boolean deserialize() default true;

// 序列化特性,等价于jackson的@JsonProperty.with()

SerializerFeature[] serialzeFeatures() default {};

// 反序列化特性,等价于jackson的@JsonFormat.with()

Feature[] parseFeatures() default {};

// 对属性进行打标,便于在序列化时进行exclude或include,等价于jackson的@JsonView

String label() default “”;

// 序列化时将字段内容直接输出,不经过转义,等价于jackson的@JsonRawValue

boolean jsonDirect() default false;

// 指定序列化时使用的Serializer Class,等价于jackson的@JsonSerialize

Class<?> serializeUsing() default Void.class;

// 指定反序列化时使用的Deserializer Class,等价于jackson的@JsonDeserialize

Class<?> deserializeUsing() default Void.class;

// 指定反序列化时使用的字段别名,等价于jackson的@JsonAlias

String[] alternateNames() default {};

// 将字段的子属性映射到父节点上,等价于jackson的@JsonUnwrapped

boolean unwrapped() default false;

// 指定序列化时字段为null时使用的默认值,等价于jackson的@JsonProperty.defaultValue()

String defaultValue() default “”;

}

unwrapped的用法可以参考AnnotationUseJacksonReplaceFastJsonTest.java中的testJSONFieldUnwrapped

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

经过日积月累, 以下是小编归纳整理的深入了解Java虚拟机文档,希望可以帮助大家过关斩将顺利通过面试。
由于整个文档比较全面,内容比较多,篇幅不允许,下面以截图方式展示 。







由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

经过日积月累, 以下是小编归纳整理的深入了解Java虚拟机文档,希望可以帮助大家过关斩将顺利通过面试。
由于整个文档比较全面,内容比较多,篇幅不允许,下面以截图方式展示 。

[外链图片转存中…(img-azzCUiX3-1712490517770)]
[外链图片转存中…(img-TjfOBnOp-1712490517770)]
[外链图片转存中…(img-uZDoqmBi-1712490517771)]
[外链图片转存中…(img-zNALdeUU-1712490517771)]
[外链图片转存中…(img-GB6rmj99-1712490517771)]
[外链图片转存中…(img-ZOt2FFrw-1712490517772)]
[外链图片转存中…(img-HyRcIcZ6-1712490517772)]

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值