java中常见的json解析方法、库以及性能对比

常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,json-lib。

分析这段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还是来继续搞笑的。

转载声明:性能比较部分由客由熊能创作 © 飞污熊博客。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )