fastjson总结

本文详细介绍了fastjson的序列化API,特别是`JSON.toJSONString()`方法及其常用的`SerializeFeature`配置,如WriteMapNullValue、WriteNullListAsEmpty等。通过实例展示了如何控制序列化过程,包括是否输出null值、枚举的序列化方式、日期格式化以及特殊字符转义等。

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

** fastjson 版本: 1.2.36 **

主要 API

序列化 API (String JSON.toJSONString(Object …)) : 将对象序列化为 json 字符串
反序列化 API (T JSON.parseObject(String str, …)) 将 json 字符串序列化为对象.

JSON.toJSONString(Object …)

在这里插入图片描述
有多个重载方法,不同的参数对序列化过程进行控制。可以看到,主要是通过三个参数来对序列化进行干预的,SerializeConfig 这是序列化全局配置, SerializeFilter 序列化过滤器,SerializeFeature 这是fastjson自定义的特征枚举变量,定制序列化过程。

SerializeFeature

为什么先说这个,因为这个应用范围最广,能够覆盖大部分的序列化要求。
这是一个枚举类,列举了一系列序列化的参数。
在这里插入图片描述在这里插入图片描述

package com.alibaba.fastjson.serializer;
/**
 * 
 */
public enum SerializerFeature {
    QuoteFieldNames,  // 输出 Key 时是否使用双引号, 默认 true
    UseSingleQuotes,  // 输出key时使用单引号而不是双引号, 默认 false
    WriteMapNullValue,  // 是否输出值为 null 的字段, 默认 false, 默认不输出值为 null 的字段
    WriteEnumUsingToString, // Enum 输出其toString() 值,可以重写 toString 来自定义输出形式,但是这样做会带来一个问题,对应的反序列化使用的Enum的静态方法valueof可能无法识别自行生成的toString(),导致反序列化出错
    WriteEnumUsingName,    // Enum 输出其name() 值,默认 true, 如果需要序列化其 ordinal() 值, 禁用掉该选项,如何禁用具体代码见后文
    UseISO8601DateFormat, // Date使用ISO8601格式输出,默认为 false
    WriteNullListAsEmpty,  // List 字段如果为 null,输出 [] 而不是 null,默认 false
    WriteNullStringAsEmpty, // String 字段如果为 null, 输出 "",而不是 null,默认 false
    WriteNullNumberAsZero, // 数值字段如果为 null, 输出0而不是null,默认 false
    WriteNullBooleanAsFalse,  // Boolean字段如果为 null, 输出 false而不是 null,默认 false
    SkipTransientField, // 字段如果加了@Transient 注解,则不序列化该字段, 默认 true
    SortField,  // 按字段名称排序后输出, 默认 true, 会按字段名称字母排序。 
    /** @deprecated */
    @Deprecated
    WriteTabAsSpecial,
    PrettyFormat,   // 是否格式化输出
    WriteClassName, // 序列化时写入类型信息,默认 false。反序列化时需用到
    DisableCircularReferenceDetect, //消除对同一对象循环引用的问题,默认 false
    WriteSlashAsSpecial,  // 对斜杠 / 进行转义, 转义成 \/
    BrowserCompatible,
    WriteDateUseDateFormat,  // 全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
    NotWriteRootClassName,
    /** @deprecated */
    DisableCheckSpecialChar, //一个对象的字符串属性中如果有特殊字符如双引号,将会在转成json时带有反斜杠转移符。如果不需要转义,可以使用这个属性。默认为false
    BeanToArray,
    WriteNonStringKeyAsString, 
    NotWriteDefaultValue,  //  不写入默认值, 默认 false
    BrowserSecure,
    IgnoreNonFieldGetter,  // 忽略不是类字段对应的getter 方法 ,默认 false
    WriteNonStringValueAsString,
    IgnoreErrorGetter,
    WriteBigDecimalAsPlain,
    MapSortField;
}

还是举例说明吧
以老掉牙的 User 类举例

public class User {
    private String name;
    private String sex;
    private String address;
    private String defVal = "hello";  // 有默认值
    private String trans;          // get 方法加了@Transient 注解
    private int age;
    private Long seconds;
    private BigDecimal salary;
    private Boolean flag;
    private Date birth;
    private List<String> roles;
    private Map<String,Object> map;
    private Week week;
    private String nullVal;

    public enum Week {
        Mon(1), Tue(2), Wed(3), Thu(4), Fir(5), Sat(6), Sun(7);
        private int val;

        Week(Integer val) {
            this.val = val;
        }

        public int getVal() {
            return val;
        }
    }
	// 这是额外定义的getTest()方法,类中并没有 test 字段。
    public String getTest() {
        return "test";
    }

    @Transient
    public String getTrans() {
        return trans;
    }

    public void setTrans(String trans) {
        this.trans = trans;
    }
 ... 
 其余 getter/setter 方法

基础序列化;
@Test
    public void test() {
        User user = new User();
        user.setName("张三");
        user.setAge(12);
        user.setSex("1");
        user.setAddress("杭州123号\t\n\r \"京城18号\"");
        user.setWeek(User.Week.Fir);

        String userStr = JSON.toJSONString(user);
        System.out.println(userStr);
    }
    输出结果:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}

User类的 seconds, roles, nullVal 等值为 null 的字段没有输出来,说明默认情况下值为 null 的字段是不序列化的。defVal 在定义的初始化为hello,也是输出了的。另外额外定义的getTest方法,fastjson就会序列化test字段出来,哪怕类中没有 test Field。可以用 SerializeFeature.IgnoreNonFieldGetter 忽略掉这些不是Field 字段的 getter 方法。

WriteMapNullValue 是否输出值为 null 的字段

因为fastjson默认是不序列化值为 null 的字段的,加了这个选项,那么值为 null 的字段也会输出。

 String userStr = JSON.toJSONString(user, SerializerFeature.WriteMapNullValue);
 System.out.println(userStr);
输出结果:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":null,"defVal":"hello","flag":null,"map":null,"name":"张三","nullVal":null,"roles":null,"salary":null,"seconds":null,"sex":"1","test":"test","week":"Fir"}

值为 null 的 字段也输出了。

WriteNullListAsEmpty, WriteNullStringAsEmpty,,WriteNullNumberAsZero,WriteNullBooleanAsFalse

直接上代码,具体含义上面也说了。

String userStr = JSON.toJSONString(user, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullBooleanAsFalse);
 // 另外也可以这么写: String userStr = JSON.toJSONString(user, SerializerFeature.WRITE_MAP_NULL_FEATURES);
	WRITE_MAP_NULL_FEATURES 相当于这四个特性。
	
 System.out.println(userStr);
输出:

{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":null,"defVal":"hello","flag":false,"map":null,"name":"张三","nullVal":"","roles":[],"salary":0,"seconds":0,"sex":"1","test":"test","week":"Fir"}

可以看到roles序列化化为 [], salay序列化为 0,flag 序列化为false, nullVal序列化为 “” (空字符串),

WriteEnumUsingToString 和 WriteEnumUsingName

WriteEnumUsingToString 会使用 enum 的 toString() 返回值来序列化枚举类型。例如在上例中,我们在enum Week 中重写 toString() 方法。因为enum默认的 toString 方法就是输出其 name 值,如果不重写 toString() 方法,其输出就是其 name 值

public enum Week {
        Mon(1), Tue(2), Wed(3), Thu(4), Fir(5), Sat(6), Sun(7);
        private int val;

        Week(Integer val) {
            this.val = val;
        }

        public int getVal() {
            return val;
        }

        @Override
        public String toString() {
            return this.ordinal() + ":" + this.name();
        }

    }
String userStr = JSON.toJSONString(user, SerializerFeature.WriteEnumUsingToString);
输出: 	
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"4:Fir"}

week字段的输出变成了 『4:Fir』

WriteEnumUsingName 默认为 true, fastjson 默认输出枚举类型的 name 值,如果想要输出其 ordinal 值, 将其值设置为 false 即可。怎么设置呢,这里就要用到SerializeFeature 的 config 方法了。看代码

int feature = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
String userStr = JSON.toJSONString(user, feature);
System.out.println(userStr);

输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":4}

week值变成了4, ordinal值是从 0 开始算起的,所以 Fri 的 ordinal 值为4。

PrettyFormat 格式化输出

默认情况下,输出的 json 只有一行。这个特性可以让输出进行一些格式化操作,什么意思呢,输出会有多行,有缩进,有换行。

String userStr = JSON.toJSONString(user, SerializerFeature.PrettyFormat);
输出: 
{
	"address":"杭州123号\t\n\r \"京城18号\"",
	"age":12,
	"defVal":"hello",
	"name":"张三",
	"sex":"1",
	"test":"test",
	"week":"Fir"
}
WriteSlashAsSpecial 对 / 进行转义输出
user.setAddress("杭州123号\t\n\r / /\"京城18号\"");
String userStr = JSON.toJSONString(user);
String userStr1 = JSON.toJSONString(user, SerializerFeature.WriteSlashAsSpecial);
输出:
{"address":"杭州123号\t\n\r / /\"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
{"address":"杭州123号\t\n\r \/ \/\"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}

默认情况下, / 是原样输出的,加了WriteSlashAsSpecial ,/ 被转义输出为 /

IgnoreNonFieldGetter

忽略类中非 field 字段的 getter 方法。我们看默认情况下,User 类中有一个
getTest()方法,在序列化结果中,出现了一个 test 字段,
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}
但是在 User 类中并没有一个 test 属性字段,默认情况下,fastjson 也会把这样的字段序列化出来。加了 IgnoreNonFieldGetter 之后,这样不是类 field 字段对应的getter 方法会被忽略,也就不会序列化出多余的字段了。

String userStr1 = JSON.toJSONString(user, SerializerFeature.IgnoreNonFieldGetter);
输出: 
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","week":"Fir"}

test 字段不见了。

WriteDateUseDateFormat,

全局修改日期格式,默认为false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;
JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);

 JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
 user.setBirth(new Date());
 String s = JSON.toJSONString(user, SerializerFeature.WriteDateUseDateFormat);
 输出: 
 {"address":"杭州123号\t\n\r \"京城18号\"","age":12,"birth":"2019-07-09","defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}

birth字段输出为: 2019-07-09。这种方式属于全局修改,所有的日子字段都会转换成相应的格式,如果只想对某次序列化的日期做处理,可以改用
JSON.toJSONStringWithDateFormat(user,"yyyy-MM-dd");

QuoteFieldNames, UseSingleQuotes

QuoteFieldNames特性表示序列化时将 key 用双引号包裹,默认为 true.

输出:
{"address":"杭州123号\t\n\r \"京城18号\"","age":12,"defVal":"hello","name":"张三","sex":"1","test":"test","week":"Fir"}

UseSingleQuotes 输出key时使用单引号而不是双引号, 默认 false.

代码:

 String userStr1 = JSON.toJSONString(user, SerializerFeature.UseSingleQuotes);
 输出:
{'address':'杭州123号\t\n\r "京城18号"','age':12,'defVal':'hello','name':'张三','sex':'1','test':'test','week':'Fir'}

key 现在是用单引号包裹的。如果想让 key 既不用双引号括起来,也不用单引号括起来。那么将 QuoteFieldNames 设置为 false。
代码:

int feature = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.QuoteFieldNames, false);
输出:
{address:"杭州123号\t\n\r \"京城18号\"",age:12,defVal:"hello",name:"张三",sex:"1",test:"test",week:"Fir"}

<think>好的,我现在需要回答用户关于fastjsonfastjson2的问题。首先,我得回忆一下这两个库的基本信息。fastjson是阿里巴巴开源的Java JSON处理库,对吧?它主要用于序列化和反反序列化,性能不错。用户可能想知道它的特点、用途以及为什么会有fastjson2。 接下来,我需要确认fastjsonfastjson2的区别。记得fastjson2是升级版,解决了前代的一些安全问题,比如漏洞,同时优化了性能。可能用户关心它们的差异,比如API变化、功能增强,以及兼容性如何。 然后,用户可能想知道使用场景。比如在什么情况下选择fastjson,什么时候应该升级到fastjson2。需要提到fastjson的历史问题,比如过去的安全漏洞,导致开发者可能转向其他库,而fastjson2作为改进版本试图解决这些问题。 还要注意结构清晰,分点说明。可能需要分为概述、特点对比、性能比较、安全性、使用建议等部分。确保使用中文,并且行内公式正确,不过这个问题可能不需要数学公式,但需要遵守系统指令中的格式要求。 需要检查是否有错误信息,比如fastjson2是否完全兼容fastjson,或者是否有不兼容的变更。记得之前有看过文档,fastjson2为了改进架构,可能有些API不兼容,需要提醒用户注意。 另外,用户可能关心如何迁移,是否需要修改代码,或者是否有迁移工具。可能fastjson2提供了兼容模式,或者需要手动调整部分代码。 最后,总结两者的优缺点,给出建议,比如新项目推荐使用fastjson2,旧项目谨慎升级,注意测试。同时提到社区活跃度和维护状态,fastjson2是否在积极维护,而fastjson1可能已经停止更新。 需要确保回答真实可靠,不猜测不确定的信息。如果有不确定的点,比如具体性能提升的数据,可能需要模糊处理,或者建议查阅官方文档。避免提供错误示例,比如正确的Maven依赖格式,或者API用法。 总之,整理信息,分步骤介绍fastjsonfastjson2,突出差异和优势,给出使用建议,确保用户能清晰理解两者的区别和应用场景。</think>以下是对fastjsonfastjson2的对比介绍,分步骤说明: --- ### **1. 概述** - **fastjson** 阿里巴巴开源的Java JSON处理库(2012年发布),主打高性能的序列化(Java对象→JSON字符串)与反序列化(JSON字符串→Java对象)。曾广泛用于国内Java项目,但因历史安全漏洞问题引发争议。 - **fastjson2** fastjson的升级版本(2021年发布),重构了代码架构,优化性能并修复安全问题。定位为“更安全、更高效、更易扩展”的替代方案。 --- ### **2. 核心差异对比** #### **① 性能** - **fastjson** 早期以速度快著称,但后续版本因安全补丁引入性能损耗。 - **fastjson2** 重构后性能显著提升,官方称反序列化速度比fastjson快约30%,序列化快约20%。 #### **② 安全性** - **fastjson** 存在多个高危漏洞(如`AutoType`反序列化漏洞),需频繁升级版本。 - **fastjson2** 默认关闭`AutoType`,引入更严格的白名单机制,降低安全风险。 #### **③ API兼容性** - **fastjson** 包路径为`com.alibaba.fastjson`。 - **fastjson2** 包路径改为`com.alibaba.fastjson2`,API部分兼容但非完全一致,需谨慎迁移。 --- ### **3. 功能增强** - **fastjson2新增特性** - 支持JDK新特性(如`LocalDate`、`Optional`) - 提供对JSON Schema验证的支持 - 更灵活的扩展接口(自定义序列化/反序列化逻辑) --- ### **4. 使用建议** - **优先选择fastjson2的场景** - 新项目开发 - 对安全性和性能要求高的系统 - 需要兼容新JDK特性的场景 - **谨慎迁移的情况** - 旧项目深度依赖fastjson且代码量大(需充分测试兼容性) - 使用过时Java版本(如JDK6/7) --- ### **5. 示例代码** #### **依赖配置** ```xml <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <!-- fastjson2 --> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.47</version> </dependency> ``` #### **基础用法** ```java // 序列化 String json = JSON.toJSONString(obj); // 反序列化 User user = JSON.parseObject(json, User.class); ``` --- ### **6. 总结** | **维度** | **fastjson** | **fastjson2** | |------------|-------------------|-----------------------| | 性能 | 较高(历史版本) | 更优(重构优化) | | 安全性 | 风险较高 | 显著提升 | | 维护状态 | 已停止更新 | 持续迭代 | | 适用场景 | 遗留系统维护 | 新项目/升级项目 | **推荐策略**:新项目直接采用fastjson2;旧项目逐步迁移,需验证API兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值