什么是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中用到的异常