常見的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON庫,阿里的fastjson,還有jackson,json-lib。html
{ "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數據,java
解析:git
public class Httpjson extends Thread { private String url; private Context context; private ListView listView; private JsonAdapter adapter; private Handler handler; public Httpjson(String url, ListView listView, JsonAdapter adapter, Handler handler) { super(); this.url = url; this.listView = listView; this.adapter = adapter; this.handler = handler; } @Override public void run() { URL httpUrl; try { httpUrl = new URL(url); ··· } /** * 從網絡中獲取JSON字符串,而後解析 * @param json * @return */ private List<Person> jsonParse(String json) { try { List<Person> personlist = new ArrayList<Person>(); JSONObject jsonObject = new JSONObject(json); int result = jsonObject.getInt("result"); if (result == 1) { JSONArray jsonArray = jsonObject.getJSONArray("personData"); for (int i = 0; i < jsonArray.length(); i++) { Person person = new Person(); JSONObject personData = jsonArray.getJSONObject(i); int age = personData.getInt("age"); String url = personData.getString("url"); String name = personData.getString("name"); ··· JSONArray schoolInfoArray = personData.getJSONArray("schoolInfo"); for (int j = 0; j < schoolInfoArray.length(); j++) { JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j); String schoolName = schoolInfojson.getString("School_name"); ··· } ··· } return personlist; } else { Toast.makeText(context, "erro", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); Log.e("JsonParseActivity", "json解析出現了問題"); } return null; } }
##二、gson解析 ####(1)簡介 GSON是Google提供的用來在Java對象和JSON數據之間進行映射的Java類庫。能夠將一個Json字符轉成一個Java對象,或者將一個Java轉化爲Json字符串。github
####(2)特色算法
####(3)編寫bean類 要寫出能讓gson使用的bean類,其中的key也就是名字,如date、safe這些必須一一對應起來。其次就是在bean類中,遇到花括號就寫一個class類,遇到方括號就寫一個Arraylist數組。這些就是主要規則了!內部的class類寫成內部內的形式。json
{ "date": "2014-04-23", ··· "name": "蘑菇街", "packageName": "com.mogujie", "safe": [ { "safeDes": "已經過安智市場官方認證,是正版軟件", ··· }, { "safeDes": "已經過安智市場安全檢測,請放心使用", ··· }, { "safeDes": "無任何形式的廣告", ··· } ], "screen": [ "app/com.mogujie/screen0.jpg", ··· ], "size": 6746678, ··· }
public class GsonParseMoGuBean { public String data; public String name; public String packageName; ··· public ArrayList<SafeInfo> safe; public class SafeInfo { public String safeDes; ··· } public ArrayList<String> screen; }
####(4)將json格式的字符串{}解析爲java對象數組
Java對象 /** * //將json格式的字符竄{}轉換爲java對象 */ private void jsonToJavaObjectByGson() { //1獲取或建立json數據 String json ="{\n" + "\t\"id\":2, \"name\":\"大蝦\", \n" + "\t\"price\":12.3, \n" + "\t\"imagePath\":\"http://192.168.10.165:8080/L05_Server/images/f1.jpg\"\n" + "}\n"; //2解析json數據 Gson gson =new Gson(); //第一個參數是要解析的數據,第二個參數是解析生成的java對象的類 ShopInfo shopInfo = gson.fromJson(json, ShopInfo.class); }
####(5)將json格式的字符串{}解析爲java對象的list安全
private void jsonToJavaListByGson() { //1獲取或建立json數據 String json = "[\n" + " {\n" + " \"id\": 1,\n" + " \"imagePath\": \"http://192.168.10.165:8080/f1.jpg\",\n" + " \"name\": \"大蝦 1\",\n" + " \"price\": 12.3\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"imagePath\": \"http://192.168.10.165:8080/f2.jpg\",\n" + " \"name\": \"大蝦 2\",\n" + " \"price\": 12.5\n" + " }\n" + "]"; //2解析json數據 Gson gson =new Gson(); //List<ShopInfo>:是要返回數據的集合 List<ShopInfo> shops = gson.fromJson(json,new TypeToken<List<ShopInfo>>(){}.getType()); //3顯示數據 tv_gson_orignal.setText(json); tv_gson_last.setText(shops.toString()); }
####(6)將java對象轉換爲json字符串網絡
private void javaToJSONByGson() { //1獲取或建立java數據 ShopInfo shopInfo = new ShopInfo(1,"鮑魚",250.0,"baoyu"); //2生成json數據 Gson gson = new Gson(); String json = gson.toJson(shopInfo); //3顯示數據 tv_gson_orignal.setText(shopInfo.toString()); tv_gson_last.setText(json); }
####(7)將java對象的list轉換爲json字符串[]app
/** * //將java對象的list轉換爲json字符竄 */ private void javaToJSONArrayByGson() { //1獲取或建立java數據 List<ShopInfo> shops =new ArrayList<ShopInfo>(); ShopInfo baoyu = new ShopInfo(1,"鮑魚",250.0,"baoyu"); ShopInfo longxia = new ShopInfo(1,"龍蝦",250.0,"longxia"); shops.add(baoyu); shops.add(longxia); //2生成json數據 Gson gson = new Gson(); String json = gson.toJson(shops); //3顯示數據 tv_gson_orignal.setText(shops.toString()); tv_gson_last.setText(json); }
##三、fastjson ####(1)簡介 在平常的java項目開發中,JSON的使用愈來愈頻繁,對於Json的處理工具也有不少。接下來就介紹一下阿里開源的一個高性能的JSON框架FastJson,功能完善,徹底支持標準JSON庫,如今已經愈來愈受到開發者的青睞。
####(2)特色 Fastjson 是一個 Java 語言編寫的高性能功能完善的 JSON 庫。它採用一種「假定有序快速匹配」的算法,把JSONParse的性能提高到極致,是目前Java語言中最快的JSON庫。
####(4)將 json 格式的字符串{}轉換爲 Java 對象
private void jsonToJavaObjectByFastJson() { // 1 獲取或建立 JSON 數據 String json = "{\n" + "\t\"id\":2, \"name\":\"大蝦\", \n" + "\t\"price\":12.3, \n" + "\t\"imagePath\":\"http://192.168.10.165:8080/L05_Server/images/f1.jpg\ "\n" + "}\n"; // 2 解析 JSON 數據 ShopInfo shopInfo = JSON.parseObject(json, ShopInfo.class); }
####(4)將 json 格式的字符串[]轉換爲 Java 對象的 List
private void jsonToJavaListByFastJson() { // 1 獲取或建立 JSON 數據 String json = "[\n" + " {\n"+ " \"id\": 1,\n" + " \"imagePath\": \"http://192.168.10.165:8080/f1.jpg\",\n" + " " " " " " \"name\": \"大蝦 1\",\n" + \"price\": 12.3\n" + },\n" + {\n"+ \"id\": 2,\n" + \"imagePath\": \"http://192.168.10.165:8080/f2.jpg\",\n" + " \"name\": \"大蝦 2\",\n" + " \"price\": 12.5\n" + " }\n"+ "]"; // 2 解析 JSON 數據 List<ShopInfo> shopInfos = JSON.parseArray(json, ShopInfo.class); }
####(5)將 Java 對象轉換爲 json 字符串
private void javaToJsonObjectByFastJson() { // 1 獲取 Java 對象 ShopInfo shopInfo = new ShopInfo(1, "鮑魚", 250.0, "baoyu"); // 2 生成 JSON 數據 String json = JSON.toJSONString(shopInfo); // 3 數據顯示 tv_fastjson_orignal.setText(shopInfo.toString()); tv_fastjson_last.setText(json); }
####(7)將 Java 對象的 List 轉換爲 json 字符串[]
private void javaToJsonArrayByFastJson() { // 1 獲取 Java 集合 List<ShopInfo> shops = new ArrayList<>(); ShopInfo baoyu = new ShopInfo(1, "鮑魚", 250.0, "baoyu"); ShopInfo longxia = new ShopInfo(2, "龍蝦", 251.0, "longxia"); shops.add(baoyu); shops.add(longxia); // 2 生成 JSON 數據 String json = JSON.toJSONString(shops); // 3 數據顯示 tv_fastjson_orignal.setText(shops.toString()); tv_fastjson_last.setText(json); }
##四、性能對比
選擇一個合適的JSON庫要從多個方面進行考慮:
####(1)添加maven依賴 固然首先是添加四個庫的maven依賴,公平起見,我所有使用它們最新的版本:
<!-- Json libs--> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.4</version> </dependency>
####(2)四個庫的工具類
java FastJsonUtil.java
public class FastJsonUtil { public static String bean2Json(Object obj) { return JSON.toJSONString(obj); } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return JSON.parseObject(jsonStr, objClass); } }
java GsonUtil.java
public class GsonUtil { private static Gson gson = new GsonBuilder().create(); public static String bean2Json(Object obj) { return gson.toJson(obj); } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return gson.fromJson(jsonStr, objClass); } public static String jsonFormatter(String uglyJsonStr) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); JsonParser jp = new JsonParser(); JsonElement je = jp.parse(uglyJsonStr); return gson.toJson(je); } }
java JacksonUtil.java
public class JacksonUtil { private static ObjectMapper mapper = new ObjectMapper(); public static String bean2Json(Object obj) { try { return mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } } public static <T> T json2Bean(String jsonStr, Class<T> objClass) { try { return mapper.readValue(jsonStr, objClass); } catch (IOException e) { e.printStackTrace(); return null; } } }
java JsonLibUtil.java
public class JsonLibUtil { public static String bean2Json(Object obj) { JSONObject jsonObject = JSONObject.fromObject(obj); return jsonObject.toString(); } @SuppressWarnings("unchecked") public static <T> T json2Bean(String jsonStr, Class<T> objClass) { return (T) JSONObject.toBean(JSONObject.fromObject(jsonStr), objClass); } }
####(3)準備Model類 這裏我寫一個簡單的Person類,同時屬性有Date、List、Map和自定義的類FullName,最大程度模擬真實場景。
public class Person { private String name; private FullName fullName; private int age; private Date birthday; private List<String> hobbies; private Map<String, String> clothes; private List<Person> friends; // getter/setter省略 @Override public String toString() { StringBuilder str = new StringBuilder("Person [name=" + name + ", fullName=" + fullName + ", age=" + age + ", birthday=" + birthday + ", hobbies=" + hobbies + ", clothes=" + clothes + "]\n"); if (friends != null) { str.append("Friends:\n"); for (Person f : friends) { str.append("\t").append(f); } } return str.toString(); } }
public class FullName { private String firstName; private String middleName; private String lastName; public FullName() { } public FullName(String firstName, String middleName, String lastName) { this.firstName = firstName; this.middleName = middleName; this.lastName = lastName; } // 省略getter和setter @Override public String toString() { return "[firstName=" + firstName + ", middleName=" + middleName + ", lastName=" + lastName + "]"; } }
####(4)JSON序列化性能基準測試
@BenchmarkMode(Mode.SingleShotTime) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) public class JsonSerializeBenchmark { /** * 序列化次數參數 */ @Param({"1000", "10000", "100000"}) private int count; private Person p; public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() .include(JsonSerializeBenchmark.class.getSimpleName()) .forks(1) .warmupIterations(0) .build(); Collection<RunResult> results = new Runner(opt).run(); ResultExporter.exportResult("JSON序列化性能", results, "count", "秒"); } @Benchmark public void JsonLib() { for (int i = 0; i < count; i++) { JsonLibUtil.bean2Json(p); } } @Benchmark public void Gson() { for (int i = 0; i < count; i++) { GsonUtil.bean2Json(p); } } @Benchmark public void FastJson() { for (int i = 0; i < count; i++) { FastJsonUtil.bean2Json(p); } } @Benchmark public void Jackson() { for (int i = 0; i < count; i++) { JacksonUtil.bean2Json(p); } } @Setup public void prepare() { List<Person> friends=new ArrayList<Person>(); friends.add(createAPerson("小明",null)); friends.add(createAPerson("Tony",null)); friends.add(createAPerson("陳小二",null)); p=createAPerson("邵同窗",friends); } @TearDown public void shutdown() { } private Person createAPerson(String name,List<Person> friends) { Person newPerson=new Person(); newPerson.setName(name); newPerson.setFullName(new FullName("zjj_first", "zjj_middle", "zjj_last")); newPerson.setAge(24); List<String> hobbies=new ArrayList<String>(); hobbies.add("籃球"); hobbies.add("游泳"); hobbies.add("coding"); newPerson.setHobbies(hobbies); Map<String,String> clothes=new HashMap<String, String>(); clothes.put("coat", "Nike"); clothes.put("trousers", "adidas"); clothes.put("shoes", "安踏"); newPerson.setClothes(clothes); newPerson.setFriends(friends); return newPerson; } }
說明一下,上面的代碼中
ResultExporter.exportResult("JSON序列化性能", results, "count", "秒");
這個是我本身編寫的將性能測試報告數據填充至Echarts圖,而後導出png圖片的方法,具體代碼我就不貼了,參考個人github源碼。
執行後的結果圖:
從上面的測試結果能夠看出,序列化次數比較小的時候,Gson性能最好,當不斷增長的時候到了100000,Gson明細弱於Jackson和FastJson, 這時候FastJson性能是真的牛,另外還能夠看到無論數量少仍是多,Jackson一直表現優異。而那個Json-lib簡直就是來搞笑的。^_^
####(5)JSON反序列化性能基準測試
@BenchmarkMode(Mode.SingleShotTime) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) public class JsonDeserializeBenchmark { /** * 反序列化次數參數 */ @Param({"1000", "10000", "100000"}) private int count; private String jsonStr; public static void main(String[] args) throws Exception { Options opt = new OptionsBuilder() .include(JsonDeserializeBenchmark.class.getSimpleName()) .forks(1) .warmupIterations(0) .build(); Collection<RunResult> results = new Runner(opt).run(); ResultExporter.exportResult("JSON反序列化性能", results, "count", "秒"); } @Benchmark public void JsonLib() { for (int i = 0; i < count; i++) { JsonLibUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void Gson() { for (int i = 0; i < count; i++) { GsonUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void FastJson() { for (int i = 0; i < count; i++) { FastJsonUtil.json2Bean(jsonStr, Person.class); } } @Benchmark public void Jackson() { for (int i = 0; i < count; i++) { JacksonUtil.json2Bean(jsonStr, Person.class); } } @Setup public void prepare() { 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}]}"; } @TearDown public void shutdown() { } }
執行後的結果圖:
從上面的測試結果能夠看出,反序列化的時候,Gson、Jackson和FastJson區別不大,性能都很優異,而那個Json-lib仍是來繼續搞笑的。
轉載聲明:性能比較部分由客由熊能創做 © 飛污熊博客。