介绍
移动互联网产品与服务器端通信的数据格式,如果没有特殊的需求的话,一般选择使用JSON格式,Android系统也原生的提供了JSON解析的API,但是它的速度很慢,而且没有提供简介方便的接口来提高开发者的效率和降低出错的可能。因此,通常情况下,我们都会选择其他优秀的JSON解析实现,用以替代系统的API,目前JSON解析的开源实现主要包括一下几种:
- Gson
- JackJson
- FastJson
- LoganSquare
例如有如下JSON数据(序列化:对象转换成字符串;反序列化:字符串转换成对象):
{ "data": { "cities": [ { "area": 123, "city": "anhuisheng", "people": 789 }, { "area": 456, "city": "jiangsusheng", "people": 678 } ], "location": "china" }, "retcode": 200 }
结构图如下:
Gson
Gson是Google出品的Json解析函数库,可以将JSON字符串反序列化为对应的Java对象,或者反过来将Java对象序列化为对应的字符串,免去了开发者手动通过JSONObject和JSONArray将Json字段逐个进行解析的烦恼,也减少了出错的可能性,增强了代码的质量。使用gson解析时候,对应的Java实体类无需要使用注解进行标记,支持任意复杂Java对象包括没有源代码的对象。
定义json对应的类的步骤
- 先定义成员变量名称
- 再定义成员变量的类型
- 再定义泛型的类
- 从外向类逐渐推荐
步骤一 定义JSON对应的类
public class GsonData { private Data data; private int retcode; @Override public String toString() { return "GsonData{" + "data=" + data + ", retcode=" + retcode + '}'; } public Data getData() { return data; } public void setData(Data data) { this.data = data; } public int getRetcode() { return retcode; } public void setRetcode(int retcode) { this.retcode = retcode; } }
public class Data { private Listcities; private String location; @Override public String toString() { return "Data{" + "cities=" + cities + ", location='" + location + '\'' + '}'; } public List getCities() { return cities; } public void setCities(List cities) { this.cities = cities; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } }
public class City { private int area; private String city; private int people; @Override public String toString() { return "City{" + "area=" + area + ", city='" + city + '\'' + ", people=" + people + '}'; } public int getArea() { return area; } public void setArea(int area) { this.area = area; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public int getPeople() { return people; } public void setPeople(int people) { this.people = people; } }
private GsonData getDataToGson() { GsonData obj = new GsonData(); obj.setRetcode(200); Data data=new Data(); City city1=new City(); city1.setArea(123); city1.setCity("anhuisheng"); city1.setPeople(789); City city2=new City(); city2.setArea(456); city2.setCity("jiangsusheng"); city2.setPeople(678); ArrayListcities=new ArrayList<>(); cities.add(city1); cities.add(city2); data.setCities(cities); data.setLocation("china"); obj.setData(data); return obj; }
步骤二 序列化与反序列化
序列化:
Gson gson = new Gson();String json = gson.toJson(getDataToGson());
反序列化:
Gson gson=new Gson();GsonData gsonData = gson.fromJson(JSON_STRING,GsonData.class);
Jackson
jackson是java语言的一个流行的JSON函数库,在android开发使用过程中,主要包含三部分。Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象
- jackson-core:json流处理核心库。
- jackson-databind:数据绑定函数库,实现Java对象和JSON字符串之间的相互转换。
- jackson-anntations:databind使用的注解函数库
JsonFactory:这个类是Jackson项目主要的工厂方法,主要用于配置和构建解析器(比如 JsonParser)和生成器(比如 JsonGenerator),这个工厂实例是线程安全的,如果有配置的话,可以重复使用。
JsonGenerator:这个类主要是用来生成Json格式的内容的,我们可以使用JsonFactory的方法生成一个实例。
JsonParser:这个主要是用来读取Json格式的内容,并且完成解析操作的,我们可以使用JsonFactory的方法生成一个实例。
ObjectMapper:这个类提供了Java对象和Json之间的转化,主要通过JsonParser和JsonGenerator实例来完成实际的对Json数据的读写操作。这个类是ObjectCodec的子类,主要的实现细节都在ObjectCodec里面。而且这个类可以重复使用,所以一般会创建这个类的一个单例模式,比如下面的代码
public class JacksonMapper { private static final ObjectMapper mapper = new ObjectMapper(); private JacksonMapper() { } public static ObjectMapper getInstance() { return mapper; } }
简单对象的Json数据生成
这里所说的简单对象指的是单一对象或者是对象的集合类
public String getJsonString(Object object) throws Exception { return JacksonMapper.getInstance().writeValueAsString(object); }
在这种方法中,我们直接使用ObjectMapper类的writeValueAsString(),就可以把对象的json格式作为返回值直接返回。
除此之外,我们还可以使用第二种方法,代码如下//序列化public String getJsonString1(Object object) throws Exception { ObjectMapper mapper = JacksonMapper.getInstance(); StringWriter sw = new StringWriter(); JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); mapper.writeValue(gen, object); gen.flush(); gen.close(); return sw.toString(); }
反序列化:
GsonData gsonData = JacksonMapper.getInstance().readValue(JSON_STRING, new GsonData().getClass());
由于jackson是针对Java语言通用的JSON函数库,并没有为Android优化定制过,因此函数包中包含了很多非必需的API,相比其他JSON函数库,用于Android平台会更显著的增大最终生成的APK体积。
参考:
Fastjson
fastjson是阿里巴巴公司出品的一个java语言编写的高性能且功能完善的JSON函数库,他采用一种“假定有序快速匹配”的算法,把JSON parse的性能提升到极致,号称是目前java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化,协议交互。Web输出、Android客户端等多种应用场景。
序列化:
JSON.toJSONString(getDataToGson())
反序列化:
JSON.parseObject(JSON_STRING).toString()
由于是java语言是互通的,因此,在以前的Android上使用时,Fastjson不可避免的引入了很多对于Android而言冗余的功能,从而增加了包的大小,很多人使用的就是标准版本的fastjson,但事实上,fastjson还存在一个专门为android定制的版本-fastjson-android。和标准版相比,Android版本中去掉了一些Android虚拟机dalvik不支持的功能,使得jar更小。
LoganSquare
LoganSquare是近两年崛起来的快速解析和序列化JSON的Android函数库。其底层基于jackson的streaming API,使用APT(Android Annotation Tool)实现编译时注解,从而提高JSON解析和序列化的性能。
android studio gradle配置: 对于低版本 配置:buildscript { repositories { jcenter() } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' }}apply plugin: 'com.neenbedankt.android-apt'dependencies { apt 'com.bluelinelabs:logansquare-compiler:1.3.6' compile 'com.bluelinelabs:logansquare:1.3.6' }
但是对于相对于较高的android studio 版本,Gradle不支持android-apt生成编译时注解的方式,所以改用下面方式:
annotationProcessor 'com.bluelinelabs:logansquare-compiler:1.3.6'compile 'com.bluelinelabs:logansquare:1.3.6'
第一步 定义bean
@JsonObjectpublic class GsonData { @JsonField private Data data; @JsonField private int retcode; @Override public String toString() { return "GsonData{" + "data=" + data + ", retcode=" + retcode + '}'; } public Data getData() { return data; } public void setData(Data data) { this.data = data; } public int getRetcode() { return retcode; } public void setRetcode(int retcode) { this.retcode = retcode; } }
@JsonObjectpublic class Data { @JsonField private Listcities; @JsonField private String location; @Override public String toString() { return "Data{" + "cities=" + cities + ", location='" + location + '\'' + '}'; } public List getCities() { return cities; } public void setCities(List cities) { this.cities = cities; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } }
@JsonObjectpublic class City { @JsonField private int area; @JsonField private String city; @JsonField private int people; @Override public String toString() { return "City{" + "area=" + area + ", city='" + city + '\'' + ", people=" + people + '}'; } public int getArea() { return area; } public void setArea(int area) { this.area = area; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public int getPeople() { return people; } public void setPeople(int people) { this.people = people; } }
序列化:
LoganSquare.parse(JSON_STRING, GsonData.class).toString()
反序列化:
LoganSquare.serialize(getDataToGson()).toString()
下图是官网的一张Benchmark图,从中可以看出LonganSquare和gson、jackson databind的性能对比。
单纯从性能方面来看,LoganSquare应该是完胜gson和jackson的。如果和fastjson相比较两者应该不相伯仲的。
总结起来。四个函数库的大小分别如下:
- gson:232KB
- jackson:259+47+1229=1.5M
- Fastjson:417KB
- Fastjson.android:256KB
- LoganSquare:307KB
从性能和包的大小综合考虑我们会选择fastjson.android作为基础技术堆栈中的JSON解析和序列化库。
(PS:Android studio 通过下载插件GsonFormat 可以快速实现实体类)