什么是Json?
Json(javascript Object Notation):Javascript對象表示法。是一種輕量級的數據交換格式,相比于xml這種數據交換格式來說,因為解析xml比較的復雜,而且需要編寫大段的代碼,所以客戶端和服務器的數據交換格式往往通過Json來進行交換。
Json一共有兩種數據結構:
1、一種是以 (key/value)對形式存在的無序的jsonObject對象,一個對象以“{”(左花括號)開始,“}”(右花括號)結束。每個“名稱”后跟一個“:”(冒號);“‘名稱/值’ 對”之間使用“,”(逗號)分隔。
2、另一種數據格式就是有序的value的集合,這種形式被稱為是jsonArray集合,數組是值(value)的有序集合。一個數組以“[”(左中括號)開始,“]”(右中括號)結束。值之間使用“,”(逗號)分隔。
{}雙括號表示對象;
[]中括號表示數組;
" " 雙引號內是屬性或值;
: 冒號表示后者是前者的值(這個值可以是字符串、數字、也可以是另一個數組或對象);
所以 {"name": "Michael"} 可以理解為是一個包含name為Michael的對象;
而[{"name": "Michael"},{"name": "Jerry"}]就表示包含兩個對象的數組。當然了,你也可以使用{"name":["Michael","Jerry"]}來簡化上面一部,這是一個擁有一個name數組的對象。
下面通過解析Json的三種方式來實現在Android客戶端和服務器端使用json這種數據格式來進行數據的交換。
一、解析JSON之使用原生態解析
Android客戶端通過一個AsyncTask異步任務請求服務器端的某些數據,AsyncTask兩個方法(1)獲取網絡數據:doInBackground();(2)更新UI(數據):onPostExecute()。在解析完這些數據后,onPostExecute()方法會將解析的數據內容更新到適配器,通知適配器發送改變。代碼注釋如下:
public class JsonActivity extends AppCompatActivity { PRivate ListView lv_main_jsondata; private List<UserEntity> list=new ArrayList<>();//定義一個對象集合 private ProgressDialog progress; private JsonActivity.myAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_json); lv_main_jsondata = (ListView) findViewById(R.id.lv_main_jsondata);//獲取listview控件 myAdapter = new myAdapter();//實列化對象 //給listview一個適配器,需要自己寫一個類繼承BaseAdapter lv_main_jsondata.setAdapter(myAdapter); //增加動畫加載效果 progress = new ProgressDialog(this); progress.setMessage("locating.....");//獲取動畫加載消息內容 } //1、寫一個類繼承BaseAdapter,重寫它的四個方法class myAdapter extends BaseAdapter{ @Override public int getCount() {//獲取總數量 return list.size(); } @Override public Object getItem(int position) {//獲取當前位置 return list.get(position); } @Override public long getItemId(int position) {//獲取當前位置的ID return position; } @Override public View getView(int position, View convertView, ViewGroup parent) {//獲取視圖 if (convertView==null){ convertView= LayoutInflater.from(JsonActivity.this).inflate(R.layout.dom_listview,null); DomActivity activity=new DomActivity();//實列化一個對象 //將對象的屬性增加到相對應的控件中 activity.uname= (TextView) convertView.findViewById(R.id.tv_listview_one); activity.content= (TextView) convertView.findViewById(R.id.tv_listview_two); activity.anthour= (TextView) convertView.findViewById(R.id.tv_listview_three); convertView.setTag(activity);//獲取標簽 } DomActivity domActivity= (DomActivity) convertView.getTag();//通過convertView得到標簽 //獲取對象的屬性,將每個屬性增加到它相對應的位置 domActivity.uname.setText(list.get(position).getUname()); domActivity.content.setText(list.get(position).getContent()); domActivity.anthour.setText(list.get(position).getAnthour()); return convertView; }} //獲取Json數據 public void getjson(View view){ progress.show();//更新數據之前增加動畫加載 new myTask().execute(); } //1、寫一個類繼承AsyncTask,重寫它的兩個方法 // <1、獲取網絡數據:doInBackground // <2、更新UI(數據):onPostExecute class myTask extends AsyncTask{ private StringBuffer stringBuffer; //獲取網絡數據:doInBackground @Override protected Object doInBackground(Object[] params) { //(1)、獲得數據路徑 String path=getString(R.string.path)+"android_json.xhtml"; try { //(2)、實例化url:將獲取網絡數據的路徑放到URL中。 URL url=new URL(path); //(3)/通過URL獲取連接的對象 HttpURLConnection httpURLConnection= (HttpURLConnection) url.openConnection(); //(4)、設置參數 01請求的方式:1、get;2、post; 02設置請求時間 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); //(5)、判斷響應碼是否是200 是的話就請求到數據 if (httpURLConnection.getResponseCode()==200){//如果請求到的響應碼是200 那么就要去讀取它的數據 InputStream inputStream=httpURLConnection.getInputStream();//以字節流的形式得到數據 //通過字符流(bufferedread)的形式讀取數據 BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));//將字符流轉成字節流 //實列化一個對象 stringBuffer = new StringBuffer(); String str=null;//定義一個接收的字符串 while((str=bufferedReader.readLine())!=null){//字符流讀取數據不為空 stringBuffer.append(str);//把字符流讀取的數據增加到對象中 } Log.i("test", "doInBackground: "+ stringBuffer.toString()); } //解析JSON try { // 一、使用原生態解析 //1、通過jsonobject對象獲取數據 JSONObject jsonObject=new JSONObject(stringBuffer.toString()); //2、獲取數據的屬性 String clazz=jsonObject.getString("class"); Log.i("test", "doInBackground: "+clazz); int munber=jsonObject.getInt("lists");//獲取它的數量 Log.i("test", "doInBackground: "+munber); //3、獲取集合的屬性 JSONArray array= jsonObject.getJSONArray("fqs"); for (int i = 0; i <array.length() ; i++) {//循環獲取array的長度 JSONObject object= array.getJSONObject(i);//拿到每一個對象 //通過對象獲取每個屬性 String name=object.getString("name"); String content=object.getString("content"); String anthour=object.getString("anthour"); UserEntity user=new UserEntity(name,content,anthour);//實列化一個對象,每循環一次實列化一次 list.add(user); } } catch (JSONException e) { e.printStackTrace(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }//更新UI(數據):onPostExecute @Override protected void onPostExecute(Object o) { myAdapter.notifyDataSetChanged();//通知適配器數據發生改變 progress.cancel();//動畫取消 super.onPostExecute(o); } }}二、解析JSON之GSON解析
使用Gson解析需要去下載Gson這個jar包,導入到我們的項目中。用Gson,我們可以非常輕松的實現數據對象和json對象的相互轉化,其中我們最常用的方法fromJSON(),將json對象轉換成我們需要的數據對象。代碼注釋如下:
public class JsonActivity extends AppCompatActivity { private ListView lv_main_jsondata; private List<UserEntity> list=new ArrayList<>();//定義一個對象集合 private ProgressDialog progress; private JsonActivity.myAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_json); lv_main_jsondata = (ListView) findViewById(R.id.lv_main_jsondata);//獲取listview控件 myAdapter = new myAdapter();//實列化對象 //給listview一個適配器,需要自己寫一個類繼承BaseAdapter lv_main_jsondata.setAdapter(myAdapter); //增加動畫加載效果 progress = new ProgressDialog(this); progress.setMessage("locating.....");//獲取動畫加載消息內容 } //1、寫一個類繼承BaseAdapter,重寫它的四個方法class myAdapter extends BaseAdapter{ @Override public int getCount() {//獲取總數量 return list.size(); } @Override public Object getItem(int position) {//獲取當前位置 return list.get(position); } @Override public long getItemId(int position) {//獲取當前位置的ID return position; } @Override public View getView(int position, View convertView, ViewGroup parent) {//獲取視圖 if (convertView==null){ convertView= LayoutInflater.from(JsonActivity.this).inflate(R.layout.dom_listview,null); DomActivity activity=new DomActivity();//實列化一個對象 //將對象的屬性增加到相對應的控件中 activity.uname= (TextView) convertView.findViewById(R.id.tv_listview_one); activity.content= (TextView) convertView.findViewById(R.id.tv_listview_two); activity.anthour= (TextView) convertView.findViewById(R.id.tv_listview_three); convertView.setTag(activity);//獲取標簽 } DomActivity domActivity= (DomActivity) convertView.getTag();//通過convertView得到標簽 //獲取對象的屬性,將每個屬性增加到它相對應的位置 domActivity.uname.setText(list.get(position).getUname()); domActivity.content.setText(list.get(position).getContent()); domActivity.anthour.setText(list.get(position).getAnthour()); return convertView; }} //獲取Json數據 public void getjson(View view){ progress.show();//更新數據之前增加動畫加載 new myTask().execute(); } //1、寫一個類繼承AsyncTask,重寫它的兩個方法 // <1、獲取網絡數據:doInBackground // <2、更新UI(數據):onPostExecute class myTask extends AsyncTask{ private StringBuffer stringBuffer; //獲取網絡數據:doInBackground @Override protected Object doInBackground(Object[] params) { //(1)、獲得數據路徑 String path=getString(R.string.path)+"android_json.xhtml"; try { //(2)、實例化url:將獲取網絡數據的路徑放到URL中。 URL url=new URL(path); //(3)/通過URL獲取連接的對象 HttpURLConnection httpURLConnection= (HttpURLConnection) url.openConnection(); //(4)、設置參數 01請求的方式:1、get;2、post; 02設置請求時間 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); //(5)、判斷響應碼是否是200 是的話就請求到數據 if (httpURLConnection.getResponseCode()==200){//如果請求到的響應碼是200 那么就要去讀取它的數據 InputStream inputStream=httpURLConnection.getInputStream();//以字節流的形式得到數據 //通過字符流(bufferedread)的形式讀取數據 BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));//將字符流轉成字節流 //實列化一個對象 stringBuffer = new StringBuffer(); String str=null;//定義一個接收的字符串 while((str=bufferedReader.readLine())!=null){//字符流讀取數據不為空 stringBuffer.append(str);//把字符流讀取的數據增加到對象中 } Log.i("test", "doInBackground: "+ stringBuffer.toString()); } //解析JSON //二、使用Gson解析Json Gson gson=new Gson();//實列化一個對象 //通過gson解析一個對象,將buffered流解析到a對象中 BigjsonActivity bjson=gson.fromJson(stringBuffer.toString(),BigjsonActivity.class); //通過對象獲取這個對象中相對應的屬性 String clazz=bjson.getClazz(); int munber=bjson.getLists(); Log.i("test", "doInBackground: "+clazz+" ;"+munber); list.addAll(bjson.getListuser());//將對象中的集合放入list對象集合中 } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }//更新UI(數據):onPostExecute @Override protected void onPostExecute(Object o) { myAdapter.notifyDataSetChanged();//通知適配器數據發生改變 progress.cancel();//動畫取消 super.onPostExecute(o); } }}三、解析JSON之FastJson解析使用FastJson需要導入第三方包,用法和Gson一樣,實現數據對象和json對象的相互轉化Gson是用fromJSON()方法,而FastJson用JSON.parSEObject()方法,然后將json對象中的集合放入我們需要的數據對象集合中。代碼注釋如下:
public class JsonActivity extends AppCompatActivity { private ListView lv_main_jsondata; private List<UserEntity> list=new ArrayList<>();//定義一個對象集合 private ProgressDialog progress; private JsonActivity.myAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_json); lv_main_jsondata = (ListView) findViewById(R.id.lv_main_jsondata);//獲取listview控件 myAdapter = new myAdapter();//實列化對象 //給listview一個適配器,需要自己寫一個類繼承BaseAdapter lv_main_jsondata.setAdapter(myAdapter); //增加動畫加載效果 progress = new ProgressDialog(this); progress.setMessage("locating.....");//獲取動畫加載消息內容 } //1、寫一個類繼承BaseAdapter,重寫它的四個方法class myAdapter extends BaseAdapter{ @Override public int getCount() {//獲取總數量 return list.size(); } @Override public Object getItem(int position) {//獲取當前位置 return list.get(position); } @Override public long getItemId(int position) {//獲取當前位置的ID return position; } @Override public View getView(int position, View convertView, ViewGroup parent) {//獲取視圖 if (convertView==null){ convertView= LayoutInflater.from(JsonActivity.this).inflate(R.layout.dom_listview,null); DomActivity activity=new DomActivity();//實列化一個對象 //將對象的屬性增加到相對應的控件中 activity.uname= (TextView) convertView.findViewById(R.id.tv_listview_one); activity.content= (TextView) convertView.findViewById(R.id.tv_listview_two); activity.anthour= (TextView) convertView.findViewById(R.id.tv_listview_three); convertView.setTag(activity);//獲取標簽 } DomActivity domActivity= (DomActivity) convertView.getTag();//通過convertView得到標簽 //獲取對象的屬性,將每個屬性增加到它相對應的位置 domActivity.uname.setText(list.get(position).getUname()); domActivity.content.setText(list.get(position).getContent()); domActivity.anthour.setText(list.get(position).getAnthour()); return convertView; }} //獲取Json數據 public void getjson(View view){ progress.show();//更新數據之前增加動畫加載 new myTask().execute(); } //1、寫一個類繼承AsyncTask,重寫它的兩個方法 // <1、獲取網絡數據:doInBackground // <2、更新UI(數據):onPostExecute class myTask extends AsyncTask{ private StringBuffer stringBuffer; //獲取網絡數據:doInBackground @Override protected Object doInBackground(Object[] params) { //(1)、獲得數據路徑 String path=getString(R.string.path)+"android_json.xhtml"; try { //(2)、實例化url:將獲取網絡數據的路徑放到URL中。 URL url=new URL(path); //(3)/通過URL獲取連接的對象 HttpURLConnection httpURLConnection= (HttpURLConnection) url.openConnection(); //(4)、設置參數 01請求的方式:1、get;2、post; 02設置請求時間 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); //(5)、判斷響應碼是否是200 是的話就請求到數據 if (httpURLConnection.getResponseCode()==200){//如果請求到的響應碼是200 那么就要去讀取它的數據 InputStream inputStream=httpURLConnection.getInputStream();//以字節流的形式得到數據 //通過字符流(bufferedread)的形式讀取數據 BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));//將字符流轉成字節流 //實列化一個對象 stringBuffer = new StringBuffer(); String str=null;//定義一個接收的字符串 while((str=bufferedReader.readLine())!=null){//字符流讀取數據不為空 stringBuffer.append(str);//把字符流讀取的數據增加到對象中 } Log.i("test", "doInBackground: "+ stringBuffer.toString()); } //解析JSON //三、使用FsatJson解析 //通過json解析一個對象,將buffered流解析到對象中 BigjsonActivity bjson =JSON.parseObject(stringBuffer.toString(),BigjsonActivity.class); //通過對象獲取這個對象中相對應的屬性 String clazz=bjson.getClazz(); int munber=bjson.getLists(); Log.i("test", "doInBackground: "+clazz+" ;"+munber); list.addAll(bjson.getFqs());//將對象中的集合放入list對象集合中 } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }//更新UI(數據):onPostExecute @Override protected void onPostExecute(Object o) { myAdapter.notifyDataSetChanged();//通知適配器數據發生改變 progress.cancel();//動畫取消 super.onPostExecute(o); } }} 總結:JSON對于移動設備來說,尤其對于網絡環境較差和流量限制的情況下,相對于XML格式的數據傳輸會更節省流量,傳輸效率更高。在這三種解析方式中FastJson是效率最高的。
Android的JSON解析部分都在包org.json下,主要有以下幾個類:
《1、JSONObject:可以看作是一個json對象,這是系統中有關JSON定義的基本單元,其包含一對兒(Key/Value)數值。它對外部(External:應用toString()方法輸出的數值)調用的響應體現為一個標準的字符串(例如:{"JSON": "Hello, World"},最外被大括號包裹,其中的Key和Value被冒號":"分隔)。其對于內部(Internal)行為的操作格式略微,例如:初始化一個JSONObject實例,引用內部的put()方法添加數值:new JSONObject().put("JSON", "Hello, World!"),在Key和Value之間是以逗號","分隔。Value的類型包括:Boolean、JSONArray、JSONObject、Number、String或者默認值JSONObject.NULL object。《2、JSONStringer:json文本構建類 ,根據官方的解釋,這個類可以幫助快速和便捷的創建JSON text。其最大的優點在于可以減少由于 格式的錯誤導致程序異常,引用這個類可以自動嚴格按照JSON語法規則(syntax rules)創建JSON text。每個JSONStringer實體只能對應創建一個JSON text。。其最大的優點在于可以減少由于格式的錯誤導致程序異常,引用這個類可以自動嚴格按照JSON語法規則(syntax rules)創建JSON text。每個JSONStringer實體只能對應創建一個JSON text。《3、JSONArray:它代表一組有序的數值。將其轉換為String輸出(toString)所表現的形式是用方括號包裹,數值以逗號”,”分隔(例如:[value1,value2,value3],大家可以親自利用簡短的代碼更加直觀的了解其格式)。這個類的內部同樣具有查詢行為,get()和opt()兩種方法都可以通過index索引返回指定的數值,put()方法用來添加或者替換數值。同樣這個類的value類型可以包括:Boolean、JSONArray、JSONObject、Number、String或者默認JSONObject.NULL object。《4、JSONTokener:json解析類。
《5、JSONException:json中用到的異常
新聞熱點
疑難解答