什么是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中用到的异常
新闻热点
疑难解答