Android原生json类只提供了很简单的几个方法,也没有内置bean的操作,但是由于其实android原生,支持比较好。比如服务器端常用的json-lib这个库,在android上面就无法使用,原因是json-lib的依赖包commons-collection无法支持;
首先,最常用的方法:从json字符串中根据键名获取相对应的值:
1、new 一个JSONObject对象,构造里放入json字符串
2、用jsonOBject对象的getString("属性名“),getInt("属性名“),或者get("属性名")方法得到对应的值
-
JSONObject jsonObject;
-
try {
-
jsonObject = new JSONObject("{name:'jack',age:12}");
-
String name = jsonObject.getString("name");
-
int age = jsonObject.getInt("age");
-
System.out.println(name+age);
-
} catch (JSONException e1) {
-
// TODO Auto-generated catch block
-
e1.printStackTrace();
-
}
如果我们想要把json字符串解析成一个java对应类的对象,就不能指望jsonObject里原生的方法了,不过我们可以继承jsonObject类并且添加一个方法,利用反射,将json字符串转化成对象,这个继承的类如下
-
package com.example.http_test;
-
import java.lang.reflect.Field;
-
import org.json.JSONObject;
-
public class SituJsonObject extends JSONObject {
-
public SituJsonObject(String jsonString) throws Exception{
-
super(jsonString);
-
}
-
/**
-
* 将一个json字符串转换成一个java类的实例
-
* @param cls
-
* @return
-
* @throws Exception
-
*/
-
public Object getBean(Class cls) throws Exception
-
{
-
//生成待输出的实例
-
Object obj = cls.newInstance();
-
//得到所有的成员变量
-
Field[] fs = cls.getDeclaredFields();
-
//对每个成员变量,从json字符串中取值,并且放到实例中
-
for (int i = 0; i < fs.length; i++) {
-
String name = fs[i].getName();
-
fs[i].setAccessible(true);//防止私有成员不能访问
-
//从json中获取这个属性所对应的值
-
Object value = this.get(name);
-
if(value==null)continue;
-
//把当前的成员变量值放到实例中
-
fs[i].set(obj, value);
-
}
-
return obj;
-
}
-
}
有了这个,就比原来的jsonObject类多了一个getBean方法,只需要传入一个class文件即可
注意:传入的class不能为内部类!!!
注意:传入的class不能为内部类!!!
注意:传入的class不能为内部类!!!
重要的事情说三遍,下面来简单的测试一下:
先写个简单的java类
注:不需要java类里有get、set方法
-
public class Person {
-
String name;
-
int age;
-
}
-
SituJsonObject situJsonObject = null;
-
try {
-
situJsonObject = new SituJsonObject("{name:'jack',age:12}");
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
System.out.println("json字符串格式错误");
-
}
-
Person p;
-
try {
-
p = (Person) situJsonObject.getBean(Person.class);
-
System.out.println("person是"+p.name+p.age);
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
System.out.println("不能解析");
-
}
如果json字符串格式不出错的话,应该很容就成功了,注意int类型的在json字符串里不要加双引号,这个原生类还不能自动进行parseInt;
原生还有一个jsonArray,里面一个常用的功能是get(下标),用来取出这个数组对应下标的值(object)
我们也添加两个方法,用来获取对应的java类
-
package com.example.http_test;
-
import org.json.JSONArray;
-
import org.json.JSONException;
-
import org.json.JSONObject;
-
public class SituJsonArray extends JSONArray {
-
public SituJsonArray(String Jsons) throws JSONException
-
{
-
super(Jsons);
-
}
-
/**
-
* 从这个数组里根据下标返回一个JSONObject对象
-
* @param index
-
* @return
-
* @throws Exception
-
*/
-
public JSONObject getJsonObject(int index) throws Exception
-
{
-
return new SituJsonObject(get(index).toString());
-
}
-
/**
-
* 通过下标返回一个java类对象,实际上就是用上一个自定义类嵌套使用
-
* @param index
-
* @param cls
-
* @return
-
* @throws JSONException
-
* @throws Exception
-
*/
-
public Object getObject(int index, Class cls) throws JSONException, Exception
-
{
-
return new SituJsonObject(get(index).toString()).getBean(cls);
-
}
-
}
有了这个,稍微遍历一下就可以把json数组里的每个类一个一个的取出来,不过条件是这个数组里只能存放一种类型的对象,下面做个测试
-
//json数组的解析
-
SituJsonArray situJsonArray = null;
-
try {
-
situJsonArray = new SituJsonArray("[{name='one',age=20},{name='two',age=30}]");
-
} catch (JSONException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
System.out.println("json字符串格式错误");
-
}
-
try {
-
//得到单个的jsonObject对象
-
System.out.println(situJsonArray.getJsonObject(0));
-
System.out.println(situJsonArray.getJsonObject(1));
-
//得到java对象
-
System.out.println(situJsonArray.getObject(0,Person.class));
-
System.out.println(situJsonArray.getObject(1,Person.class));
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
System.out.println("解析失败");
-
}
那么如何用JsonObject生成一个json字符串,答案是只能一个属性一个属性的往上put,jsonObject也没有提供普通类转json的方法
如下:
-
JSONObject jsonObject = new JSONObject();
-
try {
-
jsonObject.put("name", "jack");
-
jsonObject.put("age", 12);
-
} catch (JSONException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
System.out.println(jsonObject.toString());
-
}
输出结果:{"age":12,"name":"jack"}
那么按照刚才的思路,在我们自定义的SituJsonObject上加一个方法,用反射来写一个类所有的成员,不妨这个类叫writeBean
注:这个方法不需要java类里有get、set方法
-
public void writeBean(Object obj) throws IllegalAccessException, IllegalArgumentException, JSONException{
-
Class cls = obj.getClass();
-
Field[] fs = cls.getDeclaredFields();
-
//对每个成员变量,从json字符串中取值,并且放到实例中
-
for (int i = 0; i < fs.length; i++) {
-
String name = fs[i].getName();
-
fs[i].setAccessible(true);//防止私有成员不能访问
-
Object value = fs[i].get(obj);//从传入对象中取得相应的值
-
this.put(name, value);
-
}
-
}
来做一下简单的写入测试:
-
SituJsonObject situJsonObject = new SituJsonObject();
-
try {
-
situJsonObject.writeBean(new Person("lixiao", 14));//只需要这一句话就把所有的成员写到JsonOBject对象里去了,不需要一个一个put了
-
System.out.println(situJsonObject.toString());
-
} catch (IllegalAccessException | IllegalArgumentException
-
| JSONException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
System.out.println("反射失败");
-
}
测试结果:{"age":14,"name":"lixiao"}
如果想生成json字符串数组,只要把单个对象的json字符串简单相加就好了,不需要使用JSONArray类
我们在jsonObject里面再加一个方法,就叫getArrayString吧,接受一个list<Object>作为参数,利用之前写好的writeBean,把每个json字符串拼接起来,直接返回一个可用的字符串
-
public String getArrayString(List<Object> list) throws IllegalAccessException, IllegalArgumentException, JSONException{
-
StringBuffer sBuffer = new StringBuffer();
-
sBuffer.append("[");
-
for (Object object : list) {//把每个对象的json字符串拼接起来
-
SituJsonObject situJsonObject = new SituJsonObject();
-
situJsonObject.writeBean(object);
-
sBuffer.append(situJsonObject.toString()).append(",");
-
}
-
sBuffer.deleteCharAt(sBuffer.length()-1);//去掉最后面的逗号
-
sBuffer.append("]");
-
return sBuffer.toString();
-
}
结果是:[{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"},{"age":10,"name":"wang"}]
安卓原生的这两个类在修改过后,在一些简单场合下使用起来还是不错的,不过笔者更推荐使用阿里巴巴的fastjson类,这个jar包有单独为android出的版本,兼容性很好,而且使用起来的感觉和json-lib差不多,最可贵的是这个类号称比jackJson的速度都快,而且不需要依赖包,十分小巧轻便,本人的博客上传了,地址是http://download.csdn.net/detail/lvshaorong/9187375,是目前安卓这边的最新版本