轉(zhuǎn)載:http://www.itdecent.cn/p/b87fee2f7a23
前言
今天,我們來介紹現(xiàn)今主流的數(shù)據(jù)交換格式-JSON!
同樣作為主流為數(shù)據(jù)交換格式-XML,如果有興趣可以閱讀我寫的XML及其DOM、SAX、PULL解析方法和對(duì)比
目錄

定義
JavaScript Object Notation,JavaScript的對(duì)象表示法,是一種輕量級(jí)的文本數(shù)據(jù)交換格式。
作用
用于數(shù)據(jù)的標(biāo)記、存儲(chǔ)和傳輸。
特點(diǎn)
- 輕量級(jí)的文本數(shù)據(jù)交換格式
- 獨(dú)立于語言和平臺(tái)
- 具有自我描述性
- 讀寫速度快,解析簡(jiǎn)單
語法
JSON值
- 名稱/值
- 數(shù)組
- 對(duì)象
JSON實(shí)例
{"skill":{
"web":[
{
"name":"html",
"year":"5"
},
{
"name":"ht",
"year":"4"
}],
"database":[
{
"name":"h",
"year":"2"
}]
`}}
“名稱/值”對(duì)無序、一個(gè)對(duì)象用“{}”包括,名稱和值間用“:”相隔,對(duì)象間用“,”隔開;
"name":"html"
對(duì)象一個(gè)JSON對(duì)象包括多個(gè)名稱/值對(duì),在花括號(hào)里書寫
{ "name":"html","year":"5"}
數(shù)組數(shù)組以“[]”包括,數(shù)據(jù)的對(duì)象用逗號(hào)隔開
[{ "name":"html", "year":"5" }, { "name":"ht", "year":"4" }]
web和database都是一個(gè)數(shù)組
語法總結(jié)
數(shù)組 [ 對(duì)象 { 值/對(duì)"" } ]
數(shù)組包含對(duì)象,對(duì)象包含值/對(duì)
JSON解析
在了解了JSON后,是時(shí)候來看下如何在Android解析JSON數(shù)據(jù)
解析方法
Android解析JSON數(shù)據(jù)的方法和XML解析類似,主要有兩種:基于事件驅(qū)動(dòng)和基于文檔驅(qū)動(dòng)解析方式
基于事件驅(qū)動(dòng)
主流方式:Gson解析和Jackson解析
Gson介紹
- 簡(jiǎn)介:使用谷歌的開源庫(kù)進(jìn)行解析
- 解析方式:基于事件驅(qū)動(dòng),根據(jù)所需要取的數(shù)據(jù)通過建立一個(gè)對(duì)應(yīng)于JSON數(shù)據(jù)的JavaBean類就可以通過簡(jiǎn)單的操作解析出所需JSON數(shù)據(jù)
Gson解析
步驟1:創(chuàng)建一個(gè)與JSON數(shù)據(jù)對(duì)應(yīng)的JavaBean類(用作存儲(chǔ)需要解析的數(shù)據(jù))GSON解析的關(guān)鍵是重點(diǎn)是要根據(jù)json數(shù)據(jù)里面的結(jié)構(gòu)寫出一個(gè)對(duì)應(yīng)的javaBean,規(guī)則是:
JSON的大括號(hào)對(duì)應(yīng)一個(gè)對(duì)象,對(duì)象里面有key和value(值)。在JavaBean里面的類屬性要和key同名。
JSON的方括號(hào)對(duì)應(yīng)一個(gè)數(shù)組,所以在JavaBeanBean里面對(duì)應(yīng)的也是數(shù)組,數(shù)據(jù)里面可以有值或者對(duì)象。
如果數(shù)組里面只有值沒有key,就說明它只是一個(gè)純數(shù)組,如果里面有值有key,則說明是對(duì)象數(shù)組。純數(shù)組對(duì)應(yīng)JavaBean里面的數(shù)組類型,對(duì)象數(shù)組要在Bean里面建立一個(gè)內(nèi)部類,類屬性就是對(duì)應(yīng)的對(duì)象里面的key,建立了之后要?jiǎng)?chuàng)建一個(gè)這個(gè)內(nèi)部類的對(duì)象,名字對(duì)應(yīng)數(shù)組名。
對(duì)象里面嵌套對(duì)象時(shí)候,也要建立一個(gè)內(nèi)部類,和對(duì)象數(shù)組一樣,這個(gè)內(nèi)部類對(duì)象的名字就是父對(duì)象的key
注:JavaBean類里的屬性不一定要全部和JSON數(shù)據(jù)里的所有key相同,可以按需取數(shù)據(jù),也就是你想要哪種數(shù)據(jù),就把對(duì)應(yīng)的key屬性寫出來,注意名字一定要對(duì)應(yīng)
以下有兩個(gè)JSON文檔來說明創(chuàng)建JavaBean類的創(chuàng)建方法
簡(jiǎn)單的JSON數(shù)據(jù)1(對(duì)象)
String json = "{\"id\":1,\"name\":\"小明\",\"sex\":\"男\(zhòng)",\"age\":18,\"height\":175}";
步驟1:創(chuàng)建簡(jiǎn)單的JSON數(shù)據(jù)對(duì)應(yīng)的JavaBean類
package scut.learngson;
public class EntityStudent {
private int id;
private String name;
private String sex;
private int age;
private int height;
public void setId(int id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public void setSex(String sex){
this.sex = sex;
}
public void setAge(int age){
this.age = age;
}
public void setHeight(int height){
this.height = height;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
public String getSex(){
return sex;
}
public int getAge(){
return age;
}
public int getHeight(){
return height;
}
public void show(){
System.out.print("id=" + id + ",");
System.out.print("name=" + name+",");
System.out.print("sex=" + sex+",");
System.out.print("age=" + age+",");
System.out.println("height=" + height + ",");
}
}
復(fù)雜的JSON數(shù)據(jù)(具備嵌套)
{"translation":["車"],
"basic":
{
"phonetic":"kɑ?",
"explains":["n. 汽車;車廂","n. (Car)人名;(土)賈爾;(法、西)卡爾;(塞)察爾"]},
"query":"car",
"errorCode":0,
"web":[{"value":["汽車","車子","小汽車"],"key":"Car"},
{"value":["概念車","概念車","概念汽車"],"key":"concept car"},
{"value":["碰碰車","碰撞用汽車","碰碰汽車"],"key":"bumper car"}]
}
步驟1:復(fù)雜的JSON數(shù)據(jù)對(duì)應(yīng)的JavaBean類
package scut.httpgson;
import java.util.List;
public class student {
public String[] translation; //["車"]數(shù)組
public basic basic; //basic對(duì)象里面嵌套著對(duì)象,創(chuàng)建一個(gè)basic內(nèi)部類對(duì)象
public static class basic{ //建立內(nèi)部類
public String phonetic;
public String[] explains;
}
public String query;
public int errorCode;
public List<wb> web; //web是一個(gè)對(duì)象數(shù)組,創(chuàng)建一個(gè)web內(nèi)部類對(duì)象
public static class wb{
public String[] value;
public String key;
}
public void show(){
//輸出數(shù)組
for (int i = 0;i<translation.length;i++)
{
System.out.println(translation[i]);
}
//輸出內(nèi)部類對(duì)象
System.out.println(basic.phonetic);
//輸出內(nèi)部類數(shù)組
for (int i = 0;i<basic.explains.length;i++){
System.out.println(basic.explains[i]);
}
System.out.println(query);
System.out.println(errorCode);
for (int i = 0;i<web.size();i++){
for(int j = 0; j<web.get(i).value.length;j++)
{
System.out.println(web.get(i).value[j]);
}
System.out.println(web.get(i).key);
}
}
}
好了,是不是覺得根據(jù)JSON文本數(shù)據(jù)去轉(zhuǎn)換成JavaBean實(shí)體類很復(fù)雜呢?其實(shí)還有個(gè)簡(jiǎn)單的方法,請(qǐng)使用在線JSON字符串轉(zhuǎn)Java實(shí)體類,哈哈請(qǐng)不要打我,繼續(xù)往下看吧!
步驟2:下載并導(dǎo)入GSON需要的庫(kù)
別翻墻去谷歌官網(wǎng)下了,點(diǎn)這吧
步驟3:用Gson進(jìn)行轉(zhuǎn)換
package scut.learngson;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import com.google.gson.Gson;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Gson gson = new Gson(); //創(chuàng)建JavaBean類的對(duì)象 Student student = new EntityStudent(); String json = "{"id":1,"name":"小明","sex":"男","age":18,"height":175}"; //用GSON方法將JSON數(shù)據(jù)轉(zhuǎn)為單個(gè)類實(shí)體 student = gson.fromJson(json,Student.class); //調(diào)用student方法展示解析的數(shù)據(jù) student.show(); //將Java集合轉(zhuǎn)換為json String json2 = gson.toJson(List); System.out.println(json2); }}
總結(jié)
可以看到,利用GSON方法進(jìn)行解析,關(guān)鍵在于根據(jù)json數(shù)據(jù)里面的結(jié)構(gòu)寫出一個(gè)對(duì)應(yīng)的javaBean,而解析過程非常簡(jiǎn)單:
JavaBean對(duì)象 = gson.fromJson(son,javaBean類類名.class);
Jackson解析
解析原理:基于事件驅(qū)動(dòng),與GSON相同,先創(chuàng)建一個(gè)對(duì)應(yīng)于JSON數(shù)據(jù)的JavaBean類就可以通過簡(jiǎn)單的操作解析出所需JSON數(shù)據(jù)。但和Gson解析不同的是,GSON可按需解析,即創(chuàng)建的JavaBean類不一定完全涵蓋所要解析的JSON數(shù)據(jù),按需創(chuàng)建屬性,但Jackson解析對(duì)應(yīng)的JavaBean必須把Json數(shù)據(jù)里面的所有key都有所對(duì)應(yīng),即必須把JSON內(nèi)的數(shù)據(jù)所有解析出來,無法按需解析。但Jackson的解析速度和效率都要比GSON高
核心代碼
JSON數(shù)據(jù)
{"student": [ {"id":1,"name":"小明","sex":"男","age":18,"height":175,"date":[2013,8,11]}, {"id":2,"name":"小紅","sex":"女","age":19,"height":165,"date":[2013,8,23]}, {"id":3,"name":"小強(qiáng)","sex":"男","age":20,"height":185,"date":[2013,9,1]} ], "grade":"2"}
步驟1:建立對(duì)應(yīng)的javaBean:
建立javaBean的對(duì)應(yīng)規(guī)則和GSON一樣
package scut.learnjackson;import java.util.ArrayList;import java.util.List;class test { private List<stu> student = new ArrayList<stu>(); private int grade; public void setStudent(List<stu> student){ this.student = student; } public List<stu> getStudent(){ return student; } public void setGrade(int grade){ this.grade = grade; } public int getGrade(){ return grade; } private static class stu { private int id; private String name; private String sex; private int age; private int height; private int[] date; public void setId(int id){ this.id = id; } public int getId(){ return id; } public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setSex(String sex){ this.sex = sex; } public String getSex(){ return sex; } public void setAge(int age){ this.age = age; } public int getAge(){ return age; } public void setHeight(int height){ this.height = height; } public int getHeight(){ return height; } public void setDate(int[] date){ this.date = date; } public int[] getDate(){ return date; } } public String tostring(){ String str = ""; for (int i = 0;i<student.size();i++){ str += student.get(i).getId() + " " + student.get(i).getName() + " " + student.get(i).getSex() + " " + student.get(i).getAge() + " " + student.get(i).getHeight() ; for (int j = 0;j<student.get(i).getDate().length;j++) { str += student.get(i).getDate()[j]+ " " ; } str += "\n"; } str += "\n"+getGrade(); return str; }}
步驟2:利用Jackson方法進(jìn)行解析
package scut.learnjackson;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import org.codehaus.jackson.map.ObjectMapper;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ObjectMapper objectMapper = new ObjectMapper(); try { InputStreamReader isr = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("assets/" + "student.json"),"utf-8"); //從assets獲取json文件 BufferedReader bfr = new BufferedReader(isr); String line; StringBuilder stringBuilder = new StringBuilder(); while ((line = bfr.readLine())!=null){ stringBuilder.append(line); }//將JSON數(shù)據(jù)轉(zhuǎn)化為字符串 System.out.println(stringBuilder.toString()); System.out.println(tes.tostring()); } catch (IOException e) { e.printStackTrace(); } }}
基于文檔驅(qū)動(dòng)解析方式
主流方式:Android Studio自帶org.json解析
解析方式:基于文檔驅(qū)動(dòng),類似于XML的DOM解析方法,先把全部文件讀入到內(nèi)存中,然后遍歷所有數(shù)據(jù),然后根據(jù)需要檢索想要的數(shù)據(jù)。
需要解析的JSON數(shù)據(jù):
{"student":[ {"id":1,"name":"小明","sex":"男","age":18,"height":175}, {"id":2,"name":"小紅","sex":"女","age":19,"height":165}, {"id":3,"name":"小強(qiáng)","sex":"男","age":20,"height":185} ],"cat":"it"}
讀入本地assets文件夾里面的student.son并解析
package scut.learngson;import android.os.Bundle;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EntityStudent student = new EntityStudent(); try { //從assets獲取json文件 InputStreamReader isr = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("assets/" + "student.json")); //字節(jié)流轉(zhuǎn)字符流 BufferedReader bfr = new BufferedReader(isr); String line ; StringBuilder stringBuilder = new StringBuilder(); while ((line = bfr.readLine())!=null){ stringBuilder.append(line); }//將JSON數(shù)據(jù)轉(zhuǎn)化為字符串 JSONObject root = new JSONObject(stringBuilder.toString()); //根據(jù)鍵名獲取鍵值信息 System.out.println("root:"+root.getString("cat")); JSONArray array = root.getJSONArray("student"); for (int i = 0;i < array.length();i++) { JSONObject stud = array.getJSONObject(i); System.out.println("------------------"); System.out.print("id="+stud.getInt("id")+ ",")); System.out.print("name="+stud.getString("name")+ ",")); System.out.print("sex="+stud.getString("sex")+ ",")); System.out.print("age="+stud.getInt("age")+ ",")); System.out.println("height="+stud.getInt("height")+ ",")); bfr.close(); isr.close(); is.close();//依次關(guān)閉流 } } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } }}
GSON、Jackson、Android Studio自帶org.son解析三類方式對(duì)比
Android Studio自帶org.json
原理:基于文檔驅(qū)動(dòng)
特點(diǎn):優(yōu)點(diǎn):無缺點(diǎn):解析 XML 文件時(shí)會(huì)將整個(gè) XML 文件的內(nèi)容解析成樹型結(jié)構(gòu)存放在內(nèi)存中并創(chuàng)建新對(duì)象,比較消耗時(shí)間和內(nèi)存,解析速度和效率慢,解析方式和性能完敗GSON
GSON方式
原理:基于事件驅(qū)動(dòng)
特點(diǎn):優(yōu)點(diǎn):解析方法簡(jiǎn)單、解析效率高、占存少、靈活性高
使用情境適用于需要處理大型 JSON文檔、JSON文檔結(jié)構(gòu)復(fù)雜的場(chǎng)合
Jackson方式
原理:基于事件驅(qū)動(dòng)
特點(diǎn):優(yōu)點(diǎn):解析效率最高、在數(shù)據(jù)量大的情況優(yōu)勢(shì)尤為明顯、占存少缺點(diǎn):必須完全解析文檔,如果要按需解析的話可以拆分Json來讀取,操作和解析方法復(fù)雜;
使用情境適用于需要處理超大型JSON文檔、不需要對(duì)JSON文檔進(jìn)行按需解析、、性能要求較高的場(chǎng)合
與XML解析對(duì)比
對(duì)于同樣作為主流的數(shù)據(jù)交換格式來說,JSON相比于XML,JSON文檔大小更加小,解析方法更加簡(jiǎn)單、讀寫速度更快,所以JSON一定是你在數(shù)據(jù)交換格式的選型中的首選。
總結(jié)
本文對(duì)現(xiàn)今主流的數(shù)據(jù)傳輸格式JSON進(jìn)行了全面介紹。接下來我會(huì)介紹繼續(xù)介紹Android開發(fā)中的相關(guān)知識(shí),有興趣可以繼續(xù)關(guān)注Carson_Ho的安卓開發(fā)筆記
請(qǐng)點(diǎn)贊!因?yàn)槟銈兊墓膭?lì)是我寫作的最大動(dòng)力!
相關(guān)文章閱讀Android開發(fā):Handler異步通信機(jī)制全面解析(包含Looper、Message Queue)Android開發(fā):最全面、最易懂的Android屏幕適配解決方案Android開發(fā):5分鐘解析Activity&Fragment生命周期Android開發(fā):JSON簡(jiǎn)介及最全面解析方法!Android開發(fā):XML簡(jiǎn)介及DOM、SAX、PULL解析對(duì)比