Alibaba开源Fastjson讲解和应用

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,主要的APIJSON.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性能

fastjsongson快大约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 序列化时在最后添加内容

以上的SerializeFilterJSON.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":"红色"}



























展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie
应支付0元
点击重新获取
扫码支付

支付成功即可阅读