常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,json-lib。
-
Json-lib(项目地址:http://json-lib.sourceforge.net/index.html)。json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar,对于复杂类型的转换,json-lib对于json转换成bean还有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。json-lib在功能和性能上面都不能满足现在互联网化的需求。 ##1、java方法解析
-
JSONObject解析json对象
-
JSONArray解析json数组 例如json字符串为:
{ "personData": [ { "age": 12, "name": "nate", "schoolInfo": [ { "School_name": "清华" }, { "School_name": "北大" } ], "url": "http://pic.yesky.com/uploadImages/2014/345/36/E8C039MU0180.jpg" }, { "age": 24, "name": "jack", ··· } ], "result": 1 }
分析这段json数据,
- 第一层是一个花括号括号,即jsonObect对象,然后这个对象里面有一个personData的JSONArray数组,以及一个result属性
- 第二层personData的JSONArray数组,它里面除了属性之外,还有一个schoolInfo的JSONArray数组
- 第三次是schoolInfo的JSONArray数组里面的JSONObject对象
解析:
1public class Httpjson extends Thread { 2 private String url; 3 private Context context; 4 private ListView listView; 5 private JsonAdapter adapter; 6 private Handler handler; 7 8 public Httpjson(String url, ListView listView, JsonAdapter adapter, Handler handler) { 9 super(); 10 this.url = url; 11 this.listView = listView; 12 this.adapter = adapter; 13 this.handler = handler; 14 } 15 16 @Override 17 public void run() { 18 URL httpUrl; 19 try { 20 httpUrl = new URL(url); 21 ··· 22 } 23 24 /** 25 * 从网络中获取JSON字符串,然后解析 26 * @param json 27 * @return 28 */ 29 private List<Person> jsonParse(String json) { 30 try { 31 List<Person> personlist = new ArrayList<Person>(); 32 JSONObject jsonObject = new JSONObject(json); 33 int result = jsonObject.getInt("result"); 34 if (result == 1) { 35 JSONArray jsonArray = jsonObject.getJSONArray("personData"); 36 for (int i = 0; i < jsonArray.length(); i++) { 37 Person person = new Person(); 38 JSONObject personData = jsonArray.getJSONObject(i); 39 int age = personData.getInt("age"); 40 String url = personData.getString("url"); 41 String name = personData.getString("name"); 42 ··· 43 JSONArray schoolInfoArray = personData.getJSONArray("schoolInfo"); 44 for (int j = 0; j < schoolInfoArray.length(); j++) { 45 JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j); 46 String schoolName = schoolInfojson.getString("School_name"); 47 ··· 48 } 49 ··· 50 } 51 return personlist; 52 } else { 53 Toast.makeText(context, "erro", Toast.LENGTH_SHORT).show(); 54 } 55 } catch (JSONException e) { 56 e.printStackTrace(); 57 Log.e("JsonParseActivity", "json解析出现了问题"); 58 } 59 60 return null; 61 } 62}
##2、gson解析 ####(1)简介 GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。
####(2)特点
- 快速、高效
- 代码量少、简洁
- 面向对象
- 数据传递和解析方便
####(3)编写bean类 要写出能让gson使用的bean类,其中的key也就是名字,如date、safe这些必须一一对应起来。其次就是在bean类中,遇到花括号就写一个class类,遇到方括号就写一个Arraylist数组。这些就是主要规则了!内部的class类写成内部内的形式。
-
内部嵌套的类必须是static的,要不然解析会出错;
-
类里面的属性名必须跟Json字段里面的Key是一模一样的;
-
内部嵌套的用[]括起来的部分是一个List,所以定义为 public List<B> b,而只用{}嵌套的就定义为 public C c,
{ "date": "2014-04-23", ···
"name": "蘑菇街", "packageName": "com.mogujie", "safe": [ { "safeDes": "已通过安智市场官方认证,是正版软件", ··· }, { "safeDes": "已通过安智市场安全检测,请放心使用", ··· }, { "safeDes": "无任何形式的广告", ··· } ], "screen": [ "app/com.mogujie/screen0.jpg", ··· ], "size": 6746678, ··· }public class GsonParseMoGuBean {
1public String data; 2public String name; 3public String packageName; 4··· 5 6public ArrayList<SafeInfo> safe; 7 8public class SafeInfo { 9 public String safeDes; 10 ··· 11} 12 13public ArrayList<String> screen;}
####(4)将json格式的字符串{}解析为java对象
1Java对象 2 3/** 4 * //将json格式的字符窜{}转换为java对象 5 */ 6 private void jsonToJavaObjectByGson() { 7 8 //1获取或创建json数据 9 String json ="{\n" + 10 "\t\"id\":2, \"name\":\"大虾\", \n" + 11 "\t\"price\":12.3, \n" + 12 "\t\"imagePath\":\"http://192.168.10.165:8080/L05_Server/images/f1.jpg\"\n" + 13 "}\n"; 14 15 //2解析json数据 16 Gson gson =new Gson(); 17 18 //第一个参数是要解析的数据,第二个参数是解析生成的java对象的类 19 ShopInfo shopInfo = gson.fromJson(json, ShopInfo.class); 20 21 }
####(5)将json格式的字符串{}解析为java对象的list
1private void jsonToJavaListByGson() { 2 3 //1获取或创建json数据 4 String json = "[\n" + 5 " {\n" + 6 " \"id\": 1,\n" + 7 " \"imagePath\": \"http://192.168.10.165:8080/f1.jpg\",\n" + 8 " \"name\": \"大虾 1\",\n" + 9 " \"price\": 12.3\n" + " },\n" + " {\n" + 10 " \"id\": 2,\n" + 11 " \"imagePath\": \"http://192.168.10.165:8080/f2.jpg\",\n" + 12 " \"name\": \"大虾 2\",\n" + 13 " \"price\": 12.5\n" + " }\n" + 14 "]"; 15 16 17 //2解析json数据 18 Gson gson =new Gson(); 19 20 //List<ShopInfo>:是要返回数据的集合 21 List<ShopInfo> shops = gson.fromJson(json,new TypeToken<List<ShopInfo>>(){}.getType()); 22 23 24 //3显示数据 25 tv_gson_orignal.setText(json); 26 27 tv_gson_last.setText(shops.toString()); 28 29 }
####(6)将java对象转换为json字符串
1private void javaToJSONByGson() { 2 3 //1获取或创建java数据 4 ShopInfo shopInfo = new ShopInfo(1,"鲍鱼",250.0,"baoyu"); 5 6 7 //2生成json数据 8 Gson gson = new Gson(); 9 10 String json = gson.toJson(shopInfo); 11 12 //3显示数据 13 tv_gson_orignal.setText(shopInfo.toString()); 14 15 tv_gson_last.setText(json); 16 17 }
####(7)将java对象的list转换为json字符串[]
1/** 2 * //将java对象的list转换为json字符窜 3 */ 4 private void javaToJSONArrayByGson() { 5 6 //1获取或创建java数据 7 List<ShopInfo> shops =new ArrayList<ShopInfo>(); 8 9 ShopInfo baoyu = new ShopInfo(1,"鲍鱼",250.0,"baoyu"); 10 11 ShopInfo longxia = new ShopInfo(1,"龙虾",250.0,"longxia"); 12 13 shops.add(baoyu); 14 15 shops.add(longxia); 16 17 //2生成json数据 18 Gson gson = new Gson(); 19 20 String json = gson.toJson(shops); 21 22 23 //3显示数据 24 tv_gson_orignal.setText(shops.toString()); 25 26 tv_gson_last.setText(json); 27 }
##3、fastjson ####(1)简介 在日常的java项目开发中,JSON的使用越来越频繁,对于Json的处理工具也有很多。接下来就介绍一下阿里开源的一个高性能的JSON框架FastJson,功能完善,完全支持标准JSON库,现在已经越来越受到开发者的青睐。
####(2)特点 Fastjson 是一个 Java 语言编写的高性能功能完善的 JSON 库。它采用一种“假定有序快速匹配”的算法,把JSONParse的性能提升到极致,是目前Java语言中最快的JSON库。
####(4)将 json 格式的字符串{}转换为 Java 对象
1private void jsonToJavaObjectByFastJson() { 2 3// 1 获取或创建 JSON 数据 4 String json = "{\n" + 5"\t\"id\":2, \"name\":\"大虾\", \n" + 6"\t\"price\":12.3, \n" + 7"\t\"imagePath\":\"http://192.168.10.165:8080/L05_Server/images/f1.jpg\ "\n" + 8"}\n"; 9 10// 2 解析 JSON 数据 11ShopInfo shopInfo = JSON.parseObject(json, ShopInfo.class); 12 13}
####(4)将 json 格式的字符串[]转换为 Java 对象的 List
1private void jsonToJavaListByFastJson() { 2 3// 1 获取或创建 JSON 数据 4 String json = "[\n" + 5" {\n"+ 6" \"id\": 1,\n" + 7" \"imagePath\": 8\"http://192.168.10.165:8080/f1.jpg\",\n" + 9" " " " " " 10\"name\": \"大虾 1\",\n" + 11\"price\": 12.3\n" + },\n" + 12{\n"+ 13\"id\": 2,\n" + \"imagePath\": 14\"http://192.168.10.165:8080/f2.jpg\",\n" + 15" \"name\": \"大虾 2\",\n" + 16" \"price\": 12.5\n" + " }\n"+ 17"]"; 18 19// 2 解析 JSON 数据 20List<ShopInfo> shopInfos = JSON.parseArray(json, ShopInfo.class); 21}
####(5)将 Java 对象转换为 json 字符串
1private void javaToJsonObjectByFastJson() { 2// 1 获取 Java 对象 3ShopInfo shopInfo = new ShopInfo(1, "鲍鱼", 250.0, "baoyu"); 4// 2 生成 JSON 数据 5String json = JSON.toJSONString(shopInfo); 6// 3 数据显示 tv_fastjson_orignal.setText(shopInfo.toString()); tv_fastjson_last.setText(json); 7}
####(7)将 Java 对象的 List 转换为 json 字符串[]
1private void javaToJsonArrayByFastJson() { 2// 1 获取 Java 集合 3List<ShopInfo> shops = new ArrayList<>(); 4ShopInfo baoyu = new ShopInfo(1, "鲍鱼", 250.0, "baoyu"); 5ShopInfo longxia = new ShopInfo(2, "龙虾", 251.0, "longxia"); shops.add(baoyu); 6shops.add(longxia); 7// 2 生成 JSON 数据 8String json = JSON.toJSONString(shops); 9// 3 数据显示 tv_fastjson_orignal.setText(shops.toString()); tv_fastjson_last.setText(json); 10}
##4、性能对比
选择一个合适的JSON库要从多个方面进行考虑:
- 字符串解析成JSON性能
- 字符串解析成JavaBean性能
- JavaBean构造JSON性能
- 集合构造JSON性能
- 易用性 编写性能测试 接下来开始编写这四个库的性能测试代码。
####(1)添加maven依赖 当然首先是添加四个库的maven依赖,公平起见,我全部使用它们最新的版本:
1<!-- Json libs--> 2<dependency> 3 <groupId>net.sf.json-lib</groupId> 4 <artifactId>json-lib</artifactId> 5 <version>2.4</version> 6 <classifier>jdk15</classifier> 7</dependency> 8<dependency> 9 <groupId>com.google.code.gson</groupId> 10 <artifactId>gson</artifactId> 11 <version>2.8.2</version> 12</dependency> 13<dependency> 14 <groupId>com.alibaba</groupId> 15 <artifactId>fastjson</artifactId> 16 <version>1.2.46</version> 17</dependency> 18<dependency> 19 <groupId>com.fasterxml.jackson.core</groupId> 20 <artifactId>jackson-databind</artifactId> 21 <version>2.9.4</version> 22</dependency> 23<dependency> 24 <groupId>com.fasterxml.jackson.core</groupId> 25 <artifactId>jackson-annotations</artifactId> 26 <version>2.9.4</version> 27</dependency>
####(2)四个库的工具类
java FastJsonUtil.java
1public class FastJsonUtil { public static String bean2Json(Object obj) { return JSON.toJSONString(obj); } 2 3public static <T> T json2Bean(String jsonStr, Class<T> objClass) { 4 return JSON.parseObject(jsonStr, objClass); 5} 6}
java GsonUtil.java
1public class GsonUtil { 2 private static Gson gson = new GsonBuilder().create(); 3 4 public static String bean2Json(Object obj) { 5 return gson.toJson(obj); 6 } 7 8 public static <T> T json2Bean(String jsonStr, Class<T> objClass) { 9 return gson.fromJson(jsonStr, objClass); 10 } 11 12 public static String jsonFormatter(String uglyJsonStr) { 13 Gson gson = new GsonBuilder().setPrettyPrinting().create(); 14 JsonParser jp = new JsonParser(); 15 JsonElement je = jp.parse(uglyJsonStr); 16 return gson.toJson(je); 17 } 18}
java JacksonUtil.java
1public class JacksonUtil { private static ObjectMapper mapper = new ObjectMapper(); 2 3public static String bean2Json(Object obj) { 4 try { 5 return mapper.writeValueAsString(obj); 6 } catch (JsonProcessingException e) { 7 e.printStackTrace(); 8 return null; 9 } 10} 11 12public static <T> T json2Bean(String jsonStr, Class<T> objClass) { 13 try { 14 return mapper.readValue(jsonStr, objClass); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 return null; 18 } 19} 20} 21
java JsonLibUtil.java
1public class JsonLibUtil { 2 3 public static String bean2Json(Object obj) { 4 JSONObject jsonObject = JSONObject.fromObject(obj); 5 return jsonObject.toString(); 6 } 7 8 @SuppressWarnings("unchecked") 9 public static <T> T json2Bean(String jsonStr, Class<T> objClass) { 10 return (T) JSONObject.toBean(JSONObject.fromObject(jsonStr), objClass); 11 } 12}
####(3)准备Model类 这里我写一个简单的Person类,同时属性有Date、List、Map和自定义的类FullName,最大程度模拟真实场景。
1public class Person { 2 private String name; 3 private FullName fullName; 4 private int age; 5 private Date birthday; 6 private List<String> hobbies; 7 private Map<String, String> clothes; 8 private List<Person> friends; 9 10 // getter/setter省略 11 12 @Override 13 public String toString() { 14 StringBuilder str = new StringBuilder("Person [name=" + name + ", fullName=" + fullName + ", age=" 15 + age + ", birthday=" + birthday + ", hobbies=" + hobbies 16 + ", clothes=" + clothes + "]\n"); 17 if (friends != null) { 18 str.append("Friends:\n"); 19 for (Person f : friends) { 20 str.append("\t").append(f); 21 } 22 } 23 return str.toString(); 24 } 25 26} 27 28 29public class FullName { 30 private String firstName; 31 private String middleName; 32 private String lastName; 33 34 public FullName() { 35 } 36 37 public FullName(String firstName, String middleName, String lastName) { 38 this.firstName = firstName; 39 this.middleName = middleName; 40 this.lastName = lastName; 41 } 42 43 // 省略getter和setter 44 45 @Override 46 public String toString() { 47 return "[firstName=" + firstName + ", middleName=" 48 + middleName + ", lastName=" + lastName + "]"; 49 } 50}
####(4)JSON序列化性能基准测试
1@BenchmarkMode(Mode.SingleShotTime) 2@OutputTimeUnit(TimeUnit.SECONDS) 3@State(Scope.Benchmark) 4public class JsonSerializeBenchmark { 5 /** 6 * 序列化次数参数 7 */ 8 @Param({"1000", "10000", "100000"}) 9 private int count; 10 11 private Person p; 12 13 public static void main(String[] args) throws Exception { 14 Options opt = new OptionsBuilder() 15 .include(JsonSerializeBenchmark.class.getSimpleName()) 16 .forks(1) 17 .warmupIterations(0) 18 .build(); 19 Collection<RunResult> results = new Runner(opt).run(); 20 ResultExporter.exportResult("JSON序列化性能", results, "count", "秒"); 21 } 22 23 @Benchmark 24 public void JsonLib() { 25 for (int i = 0; i < count; i++) { 26 JsonLibUtil.bean2Json(p); 27 } 28 } 29 30 @Benchmark 31 public void Gson() { 32 for (int i = 0; i < count; i++) { 33 GsonUtil.bean2Json(p); 34 } 35 } 36 37 @Benchmark 38 public void FastJson() { 39 for (int i = 0; i < count; i++) { 40 FastJsonUtil.bean2Json(p); 41 } 42 } 43 44 @Benchmark 45 public void Jackson() { 46 for (int i = 0; i < count; i++) { 47 JacksonUtil.bean2Json(p); 48 } 49 } 50 51 @Setup 52 public void prepare() { 53 List<Person> friends=new ArrayList<Person>(); 54 friends.add(createAPerson("小明",null)); 55 friends.add(createAPerson("Tony",null)); 56 friends.add(createAPerson("陈小二",null)); 57 p=createAPerson("邵同学",friends); 58 } 59 60 @TearDown 61 public void shutdown() { 62 } 63 64 private Person createAPerson(String name,List<Person> friends) { 65 Person newPerson=new Person(); 66 newPerson.setName(name); 67 newPerson.setFullName(new FullName("zjj_first", "zjj_middle", "zjj_last")); 68 newPerson.setAge(24); 69 List<String> hobbies=new ArrayList<String>(); 70 hobbies.add("篮球"); 71 hobbies.add("游泳"); 72 hobbies.add("coding"); 73 newPerson.setHobbies(hobbies); 74 Map<String,String> clothes=new HashMap<String, String>(); 75 clothes.put("coat", "Nike"); 76 clothes.put("trousers", "adidas"); 77 clothes.put("shoes", "安踏"); 78 newPerson.setClothes(clothes); 79 newPerson.setFriends(friends); 80 return newPerson; 81 } 82}
说明一下,上面的代码中
ResultExporter.exportResult("JSON序列化性能", results, "count", "秒");
这个是我自己编写的将性能测试报告数据填充至Echarts图,然后导出png图片的方法,具体代码我就不贴了,参考我的github源码。
执行后的结果图: 
从上面的测试结果可以看出,序列化次数比较小的时候,Gson性能最好,当不断增加的时候到了100000,Gson明细弱于Jackson和FastJson, 这时候FastJson性能是真的牛,另外还可以看到不管数量少还是多,Jackson一直表现优异。而那个Json-lib简直就是来搞笑的。^_^
####(5)JSON反序列化性能基准测试
1@BenchmarkMode(Mode.SingleShotTime) 2@OutputTimeUnit(TimeUnit.SECONDS) 3@State(Scope.Benchmark) 4public class JsonDeserializeBenchmark { 5 /** 6 * 反序列化次数参数 7 */ 8 @Param({"1000", "10000", "100000"}) 9 private int count; 10 11 private String jsonStr; 12 13 public static void main(String[] args) throws Exception { 14 Options opt = new OptionsBuilder() 15 .include(JsonDeserializeBenchmark.class.getSimpleName()) 16 .forks(1) 17 .warmupIterations(0) 18 .build(); 19 Collection<RunResult> results = new Runner(opt).run(); 20 ResultExporter.exportResult("JSON反序列化性能", results, "count", "秒"); 21 } 22 23 @Benchmark 24 public void JsonLib() { 25 for (int i = 0; i < count; i++) { 26 JsonLibUtil.json2Bean(jsonStr, Person.class); 27 } 28 } 29 30 @Benchmark 31 public void Gson() { 32 for (int i = 0; i < count; i++) { 33 GsonUtil.json2Bean(jsonStr, Person.class); 34 } 35 } 36 37 @Benchmark 38 public void FastJson() { 39 for (int i = 0; i < count; i++) { 40 FastJsonUtil.json2Bean(jsonStr, Person.class); 41 } 42 } 43 44 @Benchmark 45 public void Jackson() { 46 for (int i = 0; i < count; i++) { 47 JacksonUtil.json2Bean(jsonStr, Person.class); 48 } 49 } 50 51 @Setup 52 public void prepare() { 53 jsonStr="{\"name\":\"邵同学\",\"fullName\":{\"firstName\":\"zjj_first\",\"middleName\":\"zjj_middle\",\"lastName\":\"zjj_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":[{\"name\":\"小明\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null},{\"name\":\"Tony\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null},{\"name\":\"陈小二\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null}]}"; 54 } 55 56 @TearDown 57 public void shutdown() { 58 } 59}
执行后的结果图: 
从上面的测试结果可以看出,反序列化的时候,Gson、Jackson和FastJson区别不大,性能都很优异,而那个Json-lib还是来继续搞笑的。
转载声明:性能比较部分由客由熊能创作 © 飞污熊博客。