您的位置:首页 > Web前端 > JavaScript

Alibaba开源Fastjson讲解和应用

2017-11-04 14:51 513 查看

1.   下载jar包

方式一:maven中央仓库: http://central.maven.org/maven2/com/alibaba/fastjson/
方式二:Sourceforge.net : https://sourceforge.net/projects/fastjson/files/

Maven项目pom.xml配置方法

Java版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version> 1.2.39</version>
</dependency>
安卓版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.64.android</version>
</dependency>

2.   主要API

fastjson入口类是com.alibaba.fastjson.JSON,主要的API是JSON.toJSONString,和parseObject。

package com.alibaba.fastjson;
public abstract class JSON {
public static final String toJSONString(Object object);
public static final <T> T parseObject(String text, Class<T> clazz, Feature... features);
}
序列化方法:String jsonString = JSON.toJSONString(obj);
反序列化方法:VO vo = JSON.parseObject("...", VO.class);
泛型反序列化:
import com.alibaba.fastjson.TypeReference;
List<VO> list = JSON.parseObject("...", new TypeReference<List<VO>>() {});


3.   快速入门案例

import java.util.ArrayList;
import java.util.List;

/**
* 部门表
* 2017年11月3日 下午10:45:07
* @author HASEE
*/
public class Dept {
private long id;
private String name;
private List<Employee> employees = new ArrayList<Employee>();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public void addEmployee(Employee employee) {
employees.add(employee);
}
@Override
public String toString() {
return "Dept [id=" + id + ", name=" + name + ", employees=" + employees + "]";
}

}
/**
* 员工表
* 2017年11月3日 下午10:45:16
* @author HASEE
*/
public class Employee {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


对象转换为JSON格式字符串

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
Dept dept = new Dept();
dept.setId(1L);
dept.setName("开发部");
Employee e1 = new Employee();
e1.setId(1L);
e1.setName("张三");
Employee e2 = new Employee();
e2.setId(2L);
e2.setName("李四");
dept.addEmployee(e1);
dept.addEmployee(e2);
String jsonString = JSON.toJSONString(dept);
System.out.println(jsonString);
}
}

输出结果:

{
"employees": [
{
"id": 1,
"name": "张三"
},
{
"id": 2,
"name": "李四"
}
],
"id": 1,
"name": "开发部"
}

JSON字符串转换为对象

import com.alibaba.fastjson.JSON;

public class Test {

public static void main(String[] args) {
String jsonString = "{\"employees\":[{\"id\":1,\"name\":\"张三\"},{\"id\":2,\"name\":\"李四\"}],\"id\":1,\"name\":\"开发部\"}";
Dept dept = JSON.parseObject(jsonString, Dept.class);
System.out.println(dept);
}

}
输出结果

Dept [id=1, name=开发部, employees=[com.rabbit.fastjson.Employee@69663380, com.rabbit.fastjson.Employee@5b37e0d2]]


4.   性能介绍

fastjson是目前java语言中最快的json库,比自称最快的jackson速度要快,第三方独立测试结果看这里:https://github.com/eishay/jvm-serializers/wiki
自行做性能测试时,关闭循环引用检测的功能。
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)
VO vo = JSON.parseObject("...", VO.class, Feature.DisableCircularReferenceDetect)

这里有jackson作者cowtowncoder等人对fastjson的性能评价:https://groups.google.com/forum/#!topic/java-serialization-benchmarking/8eS1KOquAhw

5.   Fastjson VS gson性能

fastjson比gson快大约6倍,测试结果上这里:https://github.com/eishay/jvm-serializers/wiki/Staging-Results 

6.   自定义日期格式

fastjson处理日期的API很简单,例如:
JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS")

使用ISO-8601日期格式
JSON.toJSONString(obj, SerializerFeature.UseISO8601DateFormat);

全局修改日期格式

JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat)


反序列化能够自动识别如下日期格式:
ISO-8601日期格式
yyyy-MM-dd
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ss.SSS
毫秒数字
毫秒数字字符串
.NET JSON日期格式
new Date(198293238)

7.自定义序列化

你可以使用SimplePrePropertyFilter过滤字段,详细看这里:https://github.com/alibaba/fastjson/wiki/%E4%BD%BF%E7%94%A8SimplePropertyPreFilter%E8%BF%87%E6%BB%A4%E5%B1%9E%E6%80%A7(本人不要喜欢这种方式,因为代码比较繁琐,但是比较灵活,我还是喜欢下面的注解方式)

 

关于定制序列化,详细的介绍看这里:

fastjson支持多种方式定制序列化。
通过@JSONField定制序列化
通过@JSONType定制序列化
通过SerializeFilter定制序列化
通过ParseProcess定制反序列化

7.1使用@JSONField配置快速入门

使用方式:可以把@JSONField配置在字段或者getter/setter方法上,建议在字段上配置,这样配置一个就可以了

例如在字段上配置:

import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {
@JSONField(name = "ID")
private long id;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}
}

例如在getter/setter上配置:

import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {

private long id;

@JSONField(name = "ID")
public long getId() {
return id;
}

@JSONField(name = "ID")
public void setId(long id) {
this.id = id;
}
}

展示案例:

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setId(5L);
System.out.println(JSON.toJSONString(apple));
}
}
输出结果:{"ID":5}  注意看输出的key:ID是大写的,因为你的@JSONField上的name=“ID”

7.2JSONField介绍

注意:如果属性是私有的,必须又setter方法,否则无法反序列化。如果要序列化则必须提供getter方法。

package com.alibaba.fastjson.annotation;

public @interface JSONField {
// 配置序列化和反序列化的顺序,1.1.42版本之后才支持
int ordinal() default 0;

// 指定字段的名
String name() default "";

// 指定字段的格式,对日期格式有用
String format() default "";

// 是否序列化
boolean serialize() default true;

// 是否反序列化
boolean deserialize() default true;
}

7.2.1使用format配置日期格式化

import java.util.Date;

import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {
@JSONField(name = "ID")
private long id;

@JSONField(name = "CREATEDATE", format = "yyyy-MM-dd")
private Date createDate;

public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
}

测试:

import java.util.Date;

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setId(5L);
apple.setCreateDate(new Date());
System.out.println(JSON.toJSONString(apple));
}
}
结果:{"CREATEDATE":"2017-11-04","ID":5},如果对日期不用format格式化那么输出的结果就是long类型的毫秒值

7.2.2使用serialize/deserialize指定字段不序列化

import java.util.Date;

import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {
@JSONField(name = "ID")
private long id;

@JSONField(name = "CREATEDATE", format = "yyyy-MM-dd")
private Date createDate;

@JSONField(serialize = false)
private String color;

public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

测试

import java.util.Date;

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setId(5L);
apple.setCreateDate(new Date());
apple.setColor("red");
System.out.println(JSON.toJSONString(apple));
}
}
输出结果:{"CREATEDATE":"2017-11-04","ID":5},这里由于color属性设置了serialize = false,所以不会序列化

7.2.3使用ordinal指定字段序列化的顺序(很少用)

缺省fastjson序列化一个java bean,是根据fieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序。这个特性需要1.1.42以上版本。

public static class VO {
@JSONField(ordinal = 3)
private int f0;

@JSONField(ordinal = 2)
private int f1;

@JSONField(ordinal = 1)
private int f2;
}
说明:在序列化过程中会按照ordinal顺序排序

7.2.4使用serializeUsing制定属性的序列化类

有时候我们序列化的时候需要给属性拼接对应的值,例如图片信息需要拼接服务器域名等等,这时候我们可以自定义序列化的类,只要我们实现ObjectSerializer接口就可以。

public static class Model {
@JSONField(serializeUsing = ModelValueSerializer.class)
public int value;
}

public static class ModelValueSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
int features) throws IOException {
Integer value = (Integer) object;
String text = value + "元";
serializer.write(text);
}
}

测试结果:

Model model = new Model();
model.value = 100;
String json = JSON.toJSONString(model);
Assert.assertEquals("{\"value\":\"100元\"}", json);

7.3使用@JSONType配置

和JSONField类似,但JSONType配置在类上,而不是field或者getter/setter方法上。

7.4通过SerializeFilter定制序列化

通过SerializeFilter可以使用扩展编程的方式实现定制序列化。fastjson提供了多种SerializeFilter:
PropertyPreFilter 根据PropertyName判断是否序列化
PropertyFilter 根据PropertyName和PropertyValue来判断是否序列化
NameFilter 修改Key,如果需要修改Key,process返回值则可
ValueFilter 修改Value
BeforeFilter 序列化时在最前添加内容
AfterFilter 序列化时在最后添加内容
以上的SerializeFilter在JSON.toJSONString中可以使用。
本人觉得这个比较少用,所以想了解的可以看这里:https://github.com/alibaba/fastjson/wiki/SerializeFilter

7.5通过ParsePorcess定制反序列化

https://github.com/alibaba/fastjson/wiki/ParseProcess

7.6对于IE6不支持JSON带中文字符串

我们可以序列化的时候制定规则,将中文变为\uXXXX的格式,不过在页面获取后还需要手动转回来中文。

用法:

String  jsonString = JSON.toJSONString(obj, SerializerFeature.BrowserCompatible);
import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {

@JSONField
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

测试代码:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setColor("红色");
System.out.println(JSON.toJSONString(apple, SerializerFeature.BrowserCompatible));
}
}
结果:{"color":"\u7EA2\u8272"}

7.7将对象中空的值输出

默认情况下:fastjson不会输出对象中空值,因为觉得那是没用的,但是对于调用接口的人来说,空值和不返回意思是不一样的,下面就教你如何配置输出空值

JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);

SerializerFeature参数:

SerializerFeature
描述
WriteNullListAsEmpty
将Collection类型字段的字段空值输出为[]
WriteNullStringAsEmpty
将字符串类型字段的空值输出为空字符串 ""
WriteNullNumberAsZero
将数值类型字段的空值输出为0
WriteNullBooleanAsFalse
将Boolean类型字段的空值输出为false
import java.util.Date;

import com.alibaba.fastjson.annotation.JSONField;

/**
* JSONField使用实例
* 2017年11月4日 下午1:12:35
* @author HASEE
*/
public class Apple {
@JSONField(name = "ID")
private long id;

@JSONField(name = "CREATEDATE", format = "yyyy-MM-dd")
private Date createDate;

@JSONField
private String color;

public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

测试:

import com.alibaba.fastjson.JSON;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setColor("红色");
System.out.println(JSON.toJSONString(apple));
}
}
结果:{"ID":0,"color":"红色"}可以看到createDate中的值没有输出。

测试:配置空值也输出

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
apple.setColor("红色");
System.out.println(JSON.toJSONString(apple, SerializerFeature.WriteMapNullValue));
}
}
结果:{"CREATEDATE":null,"ID":0,"color":"红色"}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息