在
Android-使用Volley 连接网络中学习了Volley发送JsonRequest并获得返回的结果(JSONObject类型)。今天就来练习一下解析JSON。
一、先了解一下JSON的基本知识(详情请参考:
http://www.json.org.cn/
):
JSON
(JavaScript Object Notation) 是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。它是基于
JavaScript Programming Language
,
Standard ECMA-262 3rd Edition - December 1999
的一个子集。 JSON采用完全独立于程序语言的文本格式,但是也使用了类C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
JSON基于两种结构:
- “名称/值”对的集合(A collection of name/value pairs)。不同的编程语言中,它被理解为
对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
- 值的有序列表(An ordered list of values)。在大部分语言中,它被实现为数组(array),矢量(vector),列表(list),序列(sequence)。
这些都是常见的数据结构。目前,绝大部分编程语言都以某种形式支持它们。这使得在各种编程语言之间交换同样格式的数据成为可能。
JSON具有以下这些形式:
对象(object) 是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
数组(array) 是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
值(value) 可以是双引号括起来的字符串(
string)、数值(number)、
true、
false、
null、对象(object)或者数组(array)。这些结构可以嵌套。
字符串(string) 是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。
JSON的字符串(
string
)与C或者Java的字符串非常相似。
数值(number) 也与C或者Java的数值非常相似。只是JSON的数值没有使用八进制与十六进制格式。
同时,可以在任意标记之间添加空白。
二、Android源代码中已经集成了JSON相关代码,在目录.\libcore\json\src\main\java\org\json下面。包括内容:JSON.java、JSONArray.java、JSONException.java、
JSONObject.java、JSONStringer.java、JSONTokener.java。同时\frameworks\base\core\java\android\Util下面也有涉及到JSON的类:JsonReader.java、JsonScope.java、
JsonToken.java、JsonWriter.java。这里在
Android-使用Volley 连接网络
中的测试代码基础上,来解析JSONRequest返回的结果:
//中国天气网返回上海当天的天气数据json格式:
/*
{"weatherinfo":
{
"city":"上海",
"cityid":"101020100",
"temp1":"22℃",
"temp2":"11℃",
"weather":"小雨",
"img1":"d7.gif",
"img2":"n7.gif",
"ptime":"08:00"
}
}*/
/**
* Created by Conway on 15-11-17.
*/
public class JsonWeatherParser {
private static final String TAG = "JsonWeatherParser";
private String mcity;
private String mcityid;
private String mtemp1;
private String mtemp2;
private String mweather;
private String mptime;
private String stringjson = "{\"weatherinfo\":{\"city\":\"上海\",\"cityid\":\"101020100\",\"temp1\":\"22℃\",\"temp2\":\"11℃\",\"weather\":\"小雨\",\"img1\":\"d7.gif\",\"img2\":\"n7.gif\",\"ptime\":\"08:00\"}}";
//使用JSONObject来解析简单的JSON
public void parseWeatherJson(JSONObject jsonObject) throws JSONException {
JSONObject weatherinfo = jsonObject.getJSONObject("weatherinfo");
mcity = weatherinfo.getString("city");
mcityid = weatherinfo.getString("cityid");
mtemp1 = weatherinfo.getString("temp1");
mtemp2 = weatherinfo.getString("temp2");
mweather = weatherinfo.getString("weather");
mptime = weatherinfo.getString("ptime");
Log.i(TAG, "mcity: " + mcity + "; mcityid: " + mcityid + "; mtemp1: " + mtemp1 + "; mtemp2: +" +
mtemp2 + "; mweather: " + mweather + "; mptime: " + mptime);
//测试解析stringjson
jsonTokenerParseWeatherJson(stringjson);
}
//如果是String 类型数据,如上面定义的stringjson,可以使用下面的方法来解析。
//此方法只是以JSONTokener为跳板,最终还是使用JSONObject来获得需要的数据。
public void jsonTokenerParseWeatherJson(String json) throws JSONException {
JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
JSONObject weatherJsonObj = object.getJSONObject("weatherinfo");
mcity = weatherJsonObj.getString("city");
mcityid = weatherJsonObj.getString("cityid");
mtemp1 = weatherJsonObj.getString("temp1");
mtemp2 = weatherJsonObj.getString("temp2");
mweather = weatherJsonObj.getString("weather");
mptime = weatherJsonObj.getString("ptime");
Log.i(TAG, "mcity: " + mcity + "; mcityid: " + mcityid + "; mtemp1: " + mtemp1 + "; mtemp2: +" +
mtemp2 + "; mweather: " + mweather + "; mptime: " + mptime);
}
}
I/JsonWeatherParser: mcity: 上海; mcityid: 101020100; mtemp1: 22℃; mtemp2: +11℃; mweather: 小雨; mptime: 08:00
I/JsonWeatherParser: mcity: 上海; mcityid: 101020100; mtemp1: 22℃; mtemp2: +11℃; mweather: 小雨; mptime: 08:00
测试代码:源码链接:http://pan.baidu.com/s/1iEZuQ 密码:1jdq (VolleyNetWork.zip)
或许,JSON存在于一个inPutStream中,比如直接使用HttpURLConnection去连接网络并获得数据。此时可能会想到将inputStream转换成String类型,再使用上面的方法来解析Json,但此时其实可以使用JSONReader来解析,不妨看看JSONReader.java源码文件,里面注释里有个解析JSON的列子,下面就用一个例子来简单使用JSONReader解析JSON格式网络数据:
public class ParseWeatherJson {
public WeatherBean parseWeatherjsonStream(InputStream in) throws IOException{
JsonReader jsonReader = new JsonReader(new InputStreamReader(in));
try {
return readWeatherBean(jsonReader);
} finally {
jsonReader.close();
}
}
private WeatherBean readWeatherBean(JsonReader jsonReader) throws IOException{
Weatherinfo weatherinfo = null;
jsonReader.beginObject();
while(jsonReader.hasNext()){
String name = jsonReader.nextName();
if(name.equals("weatherinfo")){
weatherinfo = readWeatherInfo(jsonReader);
}else{
jsonReader.skipValue();
}
}
jsonReader.endObject();
return new WeatherBean(weatherinfo);
}
private Weatherinfo readWeatherInfo(JsonReader jsonReader) throws IOException {
String mcity = null;
String mcityid = null;
String mtemp1 = null;
String mtemp2 = null;
String mweather = null;
String mptime = null;
jsonReader.beginObject();
while(jsonReader.hasNext()){
String name = jsonReader.nextName();
if(name.equals("city")){
mcity = jsonReader.nextString();
}else if(name.equals("cityid")){
mcityid = jsonReader.nextString();
}else if(name.equals("temp1")){
mtemp1 = jsonReader.nextString();
}else if(name.equals("temp2")){
mtemp2 = jsonReader.nextString();
}else if(name.equals("weather")){
mweather = jsonReader.nextString();
}else if(name.equals("ptime")){
mptime = jsonReader.nextString();
}else{
jsonReader.skipValue();
}
}
jsonReader.endObject();
return new Weatherinfo(mcity, mcityid, mtemp1, mtemp2, mweather, mptime);
}
}
public class WeatherBean {
private Weatherinfo weatherinfo;
public WeatherBean(Weatherinfo weatherinfo){
this.weatherinfo = weatherinfo;
}
public Weatherinfo getWeatherInfo(){
return weatherinfo;
}
public void setWeatherInfo(Weatherinfo info){
this.weatherinfo = info;
}
}
public class Weatherinfo {
private String mcity;
private String mcityid;
private String mtemp1;
private String mtemp2;
private String mweather;
private String mptime;
public Weatherinfo(String city, String cityId, String tempOne, String tempTwo,
String weather, String time){
this.mcity = city;
this.mcityid = cityId;
this.mtemp1 = tempOne;
this.mtemp2 = tempTwo;
this.mweather = weather;
this.mptime = time;
}
public String getCity(){
return mcity;
}
public void setCity(String city){
this.mcity = city;
}
public String getCityId(){
return mcityid;
}
public void setCityId(String cityId){
this.mcityid = cityId;
}
public String getTempOne(){
return mtemp1;
}
public void setTempOne(String temp){
this.mtemp1 = temp;
}
public String getTempTwo(){
return mtemp2;
}
public void setTempTwo(String temp){
this.mtemp2 = temp;
}
public String getWeather(){
return mweather;
}
public void setWeather(String weather){
this.mweather = weather;
}
public String getTime(){
return mptime;
}
public void setTime(String time){
this.mptime = time;
}
}
上面就是使用JSONReader解析Json的简单代码,测试代码可以结合Android-HttpClient连接网络中的测试代码来测试,只需在得到stream以后,调用下面代码:
//JSONReader解析
WeatherBean weatherBean = new ParseWeatherJson().parseWeatherjsonStream(stream);
Weatherinfo weatherinfo = weatherBean.getWeatherInfo();
Log.i(TAG, "weatherinfo: " + weatherinfo.getCity() + "," + weatherinfo.getCityId() + ","
+ weatherinfo.getTempOne() + "," + weatherinfo.getTempTwo() + ","
+ weatherinfo.getWeather() + "," + weatherinfo.getTime() + ".");
测试结果:
I/NetInfoActivity(2675): weatherinfo: 上海,101020100,22℃,11℃,小雨,08:00.