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-Results6. 自定义日期格式
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/ParseProcess7.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":"红色"}
相关文章推荐
- 阿里JSon开源组件fastjson应用
- 【Android 应用开发】 FastJson 使用详解
- com.alibaba.fastjson.JSONException: syntax error, expect {, actual [, pos 0
- com.alibaba.fastjson.JSONException: unclosed string
- 阿里巴巴Json工具-Fastjson讲解
- fastjson的方法应用与java JSONObject
- FastJson简单应用
- FastJson--阿里巴巴公司开源的速度最快的Json和对象转换工具
- alibaba fastjson(json序列化器)序列化部分源码解析-2-性能优化A
- alibaba fastJson框架
- com.alibaba.fastjson.JSOnException:exepct '[' ,but {object
- 【Android 应用开发】 FastJson 使用具体解释
- com.alibaba.fastjson.JSONException: autoType is not support.
- alibaba fastjson的使用总结和心得
- com.alibaba.fastjson.JSONException: exepct '[', but {, type : class com.lvche.pocketscore.bean2.Room
- FastJson--阿里巴巴公司开源的速度最快的Json和对象转换工具
- alibaba FastJson 解析
- 阿里巴巴Json工具-Fastjson讲解
- FastJson--阿里巴巴公司开源的速度最快的Json和对象转换工具
- alibaba fastjson(json序列化器)序列化部分源码解析-2-性能优化B