<p>上篇随笔详细介绍了三种解析服务器端传过来的xml数据格式,而对于服务器端来说,返回给客户端的数据格式一般分为html、xml和json这三种格式,那么本篇随笔将讲解一下json这个知识点,包括如何通过json-lib和gson这两个json解析库来对解析我们的json数据,以及如何在我们的Android客户端解析来自服务器端的json数据,并更新到UI当中。</p><p>一、什么是json</p><p>json(Javascript Object Notation)是一种轻量级的数据交换格式,相比于xml这种数据交换格式来说,因为解析xml比较的复杂,而且需要编写大段的代码,所以客户端和服务器的数据交换格式往往通过json来进行交换。尤其是对于web开发来说,json数据格式在客户端直接可以通过javascript来进行解析。</p><p>json一共有两种数据结构,一种是以 (key/value)对形式存在的无序的jsonObject对象,一个对象以"{"(左花括号)开始,"}"(右花括号)结束。每个"名称"后跟一个":"(冒号);"'名称/值' 对"之间使用","(逗号)分隔。</p><p><img src="/up_pic/201805/290949102568.gif" title="290949102568.gif" alt="1.gif"/></p><p>例如:{"name": "xiaoluo"}, 这就是一个最简单的json对象,对于这种数据格式,key值必须要是string类型,而对于value,则可以是string、number、object、array等数据类型:</p><p><img src="/up_pic/201805/290949137967.gif" title="290949137967.gif" alt="2.gif"/></p><p>另一种数据格式就是有序的value的集合,这种形式被称为是jsonArray,数组是值(value)的有序集合。一个数组以"["(左中括号)开始,"]"(右中括号)结束。值之间使用","(逗号)分隔。</p><p><img src="/up_pic/201805/290949177083.gif" title="290949177083.gif" alt="3.gif"/></p><p>更多的有关json数据格式可以参加json的官网,http://www.json.org/json-zh.html</p><p>二、解析json数据格式</p><p>这里将使用两种json的解析库来对我们的json数据格式进行解析以及生成我们的json数据格式。</p><p>1.json-lib(http://json-lib.sourceforge.net/)</p><p>使用json-lib来进行解析,我们需要引入第三方的包,因为json-lib分为了两个版本,一个版本是针对于jdk1.3的,一个版本是针对于jdk1.5的,这里我们下载jdk1.5的这个json-lib包,其中还需要引入其他的几个jar包:</p><p>下载好这几个jar包后,加入到classpath中即可。我们来看看json-lib给我们提供的API。</p><p>我们最常用的两个类就是 JSONObject和JSONArray这两个类,分别代表了json对象和json数组,这两个类都实现了 JSON 这个接口,下面我们通过几个小例子来看看如何将我们常见的几种数据格式转换成我们的json对象(我们一般称之为JSON数据的序列化)以及再将json对象在转换成我们的数据格式(称之为反序列化)。</p><p>①简单的javabean的序列化和反序列化</p><pre class="brush:as3;toolbar:false">publicclassPerson
{
privateintid;
privateStringname;
privateStringaddress;
publicPerson()
{
}
publicintgetId()
{
returnid;
}
publicvoidsetId(intid)
{
this.id=id;
}
publicStringgetName()
{
returnname;
}
publicvoidsetName(Stringname)
{
this.name=name;
}
publicStringgetAddress()
{
returnaddress;
}
publicvoidsetAddress(Stringaddress)
{
this.address=address;
}
publicPerson(intid,Stringname,Stringaddress)
{
super();
this.id=id;
this.name=name;
this.address=address;
}
@Override
publicStringtoString()
{
return"Person[id="+id+",name="+name+",address="+address
+"]";
}
}</pre><p>首先我们定义一个简单的javabean对象,然后将一个Person对象转换成json对象,然后再将这个json对象反序列化成我们的Person对象。</p><p>我们先定义一个JsonTools类,这个类有两个静态方法,我们可以通过这两个方法来得到一个JSON类型的字符串对象,以及一个JSON对象</p><pre class="brush:as3;toolbar:false">publicclassJsonTools
{
/**
*得到一个json类型的字符串对象
*@paramkey
*@paramvalue
*@return
*/
publicstaticStringgetJsonString(Stringkey,Objectvalue)
{
JSONObjectjsonObject=newJSONObject();
//put和element都是往JSONObject对象中放入key/value对
//jsonObject.put(key,value);
jsonObject.element(key,value);
returnjsonObject.toString();
}
/**
*得到一个json对象
*@paramkey
*@paramvalue
*@return
*/
publicstaticJSONObjectgetJsonObject(Stringkey,Objectvalue)
{
JSONObjectjsonObject=newJSONObject();
jsonObject.put(key,value);
returnjsonObject;
}
}</pre><p>我们可以直接通过 JSONObject jsonObject = new JSONObject(); 这个方法就可以得到一个json对象,然后通过element()或者是put()方法来给我们的json对象添加key/value对。我们先来看看第一个例子,实现一个简单的Person对象和json对象的转换</p><pre class="brush:as3;toolbar:false"> Personperson=newPerson(1,"xiaoluo","广州");
//将Person对象转换成一个json类型的字符串对象
StringpersonString=JsonTools.getJsonString("person",person);
System.out.println(personString.toString());</pre><p>我们看看控制台的输出:</p><p>{"person":{"address":"广州","id":1,"name":"xiaoluo"}}</p><p>整个外面的大括号是一个json对象,里面有一对key/value,其中里面的{"address":"广州","id":1,"name":"xiaoluo"}就是我们转换成的json字符串对象</p><p>再来看看如何将json对象转换成我们的bean对象</p><pre class="brush:as3;toolbar:false"> JSONObjectjsonObject=JsonTools.getJsonObject("person",person);
//通过JSONObject的toBean方法可以将json对象转换成一个javabean
JSONObjectpersonObject=jsonObject.getJSONObject("person");
Personperson2=(Person)JSONObject.toBean(personObject,Person.class);
System.out.println(person2);
Person[id=1,name=xiaoluo,address=广州]
②转换List<Person>类型的对象
@Test
publicvoidtestPersonsJson()
{
List<Person>persons=newArrayList<Person>();
Personperson=newPerson(1,"xiaoluo","广州");
Personperson2=newPerson(2,"android","上海");
persons.add(person);
persons.add(person2);
StringpersonsString=JsonTools.getJsonString("persons",persons);
System.out.println(personsString);
JSONObjectjsonObject=JsonTools.getJsonObject("persons",persons);
//List<Person>相当于一个JSONArray对象
JSONArraypersonsArray=(JSONArray)jsonObject.getJSONArray("persons");
List<Person>persons2=(List<Person>)personsArray.toCollection(personsArray,Person.class);
System.out.println(persons2);
}
{"persons":[{"address":"广州","id":1,"name":"xiaoluo"},{"address":"上海","id":2,"name":"android"}]}
[Person[id=1,name=xiaoluo,address=广州],Person[id=2,name=android,address=上海]]
③List<Map<String,String>>类型的json对象转换
@Test
publicvoidtestMapJson()
{
List<Map<String,String>>list=newArrayList<Map<String,String>>();
Map<String,String>map1=newHashMap<String,String>();
map1.put("id","001");
map1.put("name","xiaoluo");
map1.put("age","20");
Map<String,String>map2=newHashMap<String,String>();
map2.put("id","002");
map2.put("name","android");
map2.put("age","33");
list.add(map1);
list.add(map2);
StringlistString=JsonTools.getJsonString("list",list);
System.out.println(listString);
JSONObjectjsonObject=JsonTools.getJsonObject("list",list);
JSONArraylistArray=jsonObject.getJSONArray("list");
List<Map<String,String>>list2=(List<Map<String,String>>)listArray.toCollection(listArray,Map.class);
System.out.println(list2);
}
{"list":[{"id":"001","age":"20","name":"xiaoluo"},{"id":"002","age":"33","name":"android"}]}
[{id=001,name=xiaoluo,age=20},{id=002,name=android,age=33}]</pre><p>通过上面的例子,我们可以了解了如何通过json-lib这个解析库来实现javabean、List、Map等数据和json数据的互相转换</p><p>2.gson(http://code.google.com/p/google-gson/)</p><p>下面我们来看看Google提供的gson这个json解析库,同样我们需要去下载gson这个jar包,导入到我们的项目中</p><p>使用gson,我们可以非常轻松的实现数据对象和json对象的相互转化,其中我们最常用的就是两个方法,一个是fromJSON(),将json对象转换成我们需要的数据对象,另一个是toJSON(),这个就是将我们的数据对象转换成json对象。下面我们也通过一个综合的例子来看看gson的使用方法:</p><pre class="brush:as3;toolbar:false">publicclassJsonService
{
publicPersongetPerson()
{
Personperson=newPerson(1,"xiaoluo","广州");
returnperson;
}
publicList<Person>getPersons()
{
List<Person>persons=newArrayList<Person>();
Personperson=newPerson(1,"xiaoluo","广州");
Personperson2=newPerson(2,"android","上海");
persons.add(person);
persons.add(person2);
returnpersons;
}
publicList<String>getString()
{
List<String>list=newArrayList<String>();
list.add("广州");
list.add("上海");
list.add("北京");
returnlist;
}
publicList<Map<String,String>>getMapList()
{
List<Map<String,String>>list=newArrayList<Map<String,String>>();
Map<String,String>map1=newHashMap<String,String>();
map1.put("id","001");
map1.put("name","xiaoluo");
map1.put("age","20");
Map<String,String>map2=newHashMap<String,String>();
map2.put("id","002");
map2.put("name","android");
map2.put("age","33");
list.add(map1);
list.add(map2);
returnlist;
}
}
publicstaticvoidmain(String[]args)
{
Gsongson=newGson();
JsonServicejsonService=newJsonService();
Personperson=jsonService.getPerson();
System.out.println("person:"+gson.toJson(person));
//对于Object类型,使用fromJson(String,Class)方法来将Json对象转换成Java对象
Personperson2=gson.fromJson(gson.toJson(person),Person.class);
System.out.println(person2);
System.out.println("------------------------------------------------");
List<Person>persons=jsonService.getPersons();
System.out.println("persons:"+gson.toJson(persons));
/*
*对于泛型对象,使用fromJson(String,Type)方法来将Json对象转换成对应的泛型对象
*newTypeToken<>(){}.getType()方法
*/
List<Person>persons2=gson.fromJson(gson.toJson(persons),newTypeToken<List<Person>>(){}.getType());
System.out.println(persons2);
System.out.println("------------------------------------------------");
List<String>list=jsonService.getString();
System.out.println("String---->"+gson.toJson(list));
List<String>list2=gson.fromJson(gson.toJson(list),newTypeToken<List<String>>(){}.getType());
System.out.println("list2---->"+list2);
System.out.println("------------------------------------------------");
List<Map<String,String>>listMap=jsonService.getMapList();
System.out.println("Map---->"+gson.toJson(listMap));
List<Map<String,String>>listMap2=gson.fromJson(gson.toJson(listMap),newTypeToken<List<Map<String,String>>>(){}.getType());
System.out.println("listMap2---->"+listMap2);
System.out.println("------------------------------------------------");
}</pre><p>看看控制台的输出:</p><pre class="brush:as3;toolbar:false">person:{"id":1,"name":"xiaoluo","address":"广州"}
Person[id=1,name=xiaoluo,address=广州]
------------------------------------------------
persons:[{"id":1,"name":"xiaoluo","address":"广州"},{"id":2,"name":"android","address":"上海"}]
[Person[id=1,name=xiaoluo,address=广州],Person[id=2,name=android,address=上海]]
------------------------------------------------
String---->["广州","上海","北京"]
list2---->[广州,上海,北京]
------------------------------------------------
Map---->[{"id":"001","age":"20","name":"xiaoluo"},{"id":"002","age":"33","name":"android"}]
listMap2---->[{id=001,age=20,name=xiaoluo},{id=002,age=33,name=android}]
------------------------------------------------</pre><p>三、在Android客户端解析服务器端的json数据</p><p>下面我们来完成一个综合的例子,Android客户端通过一个AsyncTask异步任务请求服务器端的某些数据,然后在解析完这些数据后,将得到的数据内容更新到我们的Spinner这个UI控件当中。</p><p>我们首先来看下服务器端的代码:</p><pre class="brush:as3;toolbar:false">@WebServlet("/CityServlet")
publicclassCityServletextendsHttpServlet
{
privatestaticfinallongserialVersionUID=1L;
publicCityServlet()
{
super();
}
protectedvoiddoGet(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
this.doPost(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
PrintWriterwriter=response.getWriter();
Stringtype=request.getParameter("type");
if("json".equals(type))
{
List<String>cities=newArrayList<String>();
cities.add("广州");
cities.add("上海");
cities.add("北京");
cities.add("湖南");
Map<String,List<String>>map=newHashMap<String,List<String>>();
map.put("cities",cities);
StringcitiesString=JSON.toJSONString(map);
writer.println(citiesString);
}
writer.flush();
writer.close();
}
}</pre><p>如果客户端请求的参数是type=json,则响应给客户端一个json数据格式</p><p>接着来看看客户端的代码,首先看看客户端的布局文件,其实就是一个按钮和一个Spinner控件,当点击按钮后,通过http协议请求服务器端的数据,然后在接收到后再更新我们的Spinner控件的数据</p><pre class="brush:as3;toolbar:false"><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="64dp"
android:layout_marginTop="64dp"
android:textSize="20sp"
android:text="城市"/>
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/textView1"
android:layout_toRightOf="@id/textView1"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/spinner"
android:layout_marginLeft="22dp"
android:layout_marginTop="130dp"
android:text="加载数据"/>
</RelativeLayout></pre><p>在Android客户端写一个解析json数据格式的类:</p><pre class="brush:as3;toolbar:false">publicclassJsonUtils
{
/**
*@paramcitiesString从服务器端得到的JSON字符串数据
*@return解析JSON字符串数据,放入List当中
*/
publicstaticList<String>parseCities(StringcitiesString)
{
List<String>cities=newArrayList<String>();
try
{
JSONObjectjsonObject=newJSONObject(citiesString);
JSONArrayjsonArray=jsonObject.getJSONArray("cities");
for(inti=0;i<jsonArray.length();i++)
{
cities.add(jsonArray.getString(i));
}
}
catch(Exceptione)
{
e.printStackTrace();
}
returncities;
}
}</pre><p>当然我们的HttpUtils类也不可少:</p><pre class="brush:as3;toolbar:false">publicclassHttpUtils
{
/**
*@parampath请求的服务器URL地址
*@paramencode编码格式
*@return将服务器端返回的数据转换成String
*/
publicstaticStringsendPostMessage(Stringpath,Stringencode)
{
Stringresult="";
HttpClienthttpClient=newDefaultHttpClient();
try
{
HttpPosthttpPost=newHttpPost(path);
HttpResponsehttpResponse=httpClient.execute(httpPost);
if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK)
{
HttpEntityhttpEntity=httpResponse.getEntity();
if(httpEntity!=null)
{
result=EntityUtils.toString(httpEntity,encode);
}
}
}
catch(Exceptione)
{
e.printStackTrace();
}
finally
{
httpClient.getConnectionManager().shutdown();
}
returnresult;
}
}</pre><p>最后来看看我们的MainActivity类:</p><pre class="brush:as3;toolbar:false">publicclassMainActivityextendsActivity
{
privateSpinnerspinner;
privateButtonbutton;
privateArrayAdapter<String>adapter;
privateProgressDialogdialog;
privatefinalStringCITY_PATH_JSON="http://172.25.152.34:8080/httptest/CityServlet?type=json";
@Override
protectedvoidonCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner=(Spinner)findViewById(R.id.spinner);
button=(Button)findViewById(R.id.button);
dialog=newProgressDialog(MainActivity.this);
button.setOnClickListener(newOnClickListener()
{
@Override
publicvoidonClick(Viewv)
{
dialog.setTitle("提示信息");
dialog.setMessage("loading......");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setCancelable(false);
newMyAsyncTask().execute(CITY_PATH_JSON);
}
});
}
publicclassMyAsyncTaskextendsAsyncTask<String,Void,List<String>>
{
@Override
protectedvoidonPreExecute()
{
dialog.show();
}
@Override
protectedList<String>doInBackground(String...params)
{
List<String>cities=newArrayList<String>();
StringcitiesString=HttpUtils.sendPostMessage(params[0],"utf-8");
//解析服务器端的json数据
cities=JsonUtils.parseCities(citiesString);returncities;
}
@Override
protectedvoidonPostExecute(List<String>result)
{
adapter=newArrayAdapter<String>(MainActivity.this,android.R.layout.simple_spinner_item,result);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
dialog.dismiss();
}
}
@Override
publicbooleanonCreateOptionsMenu(Menumenu)
{
getMenuInflater().inflate(R.menu.main,menu);
returntrue;
}
}</pre><p>当然别往了开启我们的网络授权</p><p><uses-permission android:name="android.permission.INTERNET"/></p><p>最后我们来看看效果图:</p><p><img src="/up_pic/201805/290949335813.jpg" title="290949335813.jpg" alt="4.jpg"/></p><p>这样我们就完成了客户端与服务器端通过json来进行数据的交换</p><p></p><p>总结:本篇随笔主要讲解了JSON这种轻量级的数据交换格式的概念,以及讲解了两种解析json数据的解析类(json-lib以及gson),最后通过一个小例子实现了在Android客户端和服务器端使用json这种数据格式来进行数据的交换。</p>