看一下opt针对如上问题的解决:
JSONObject obj = new JSONObject(json);//最外层的JSONObject对象 JSONObject user = obj.optJSONObject("user"); String name = user.optString("name"); //整形转字符串 String age = user.optString("age"); boolean isMan = user.optBoolean("isMan"); //默认值,如果没有该字段,则会返回默认值 String sex = user.optString("sex","男"); System.out.println("name:"+name+"\nage:"+age+"\nisMan:"+isMan+"\nsex:"+sex); name:alex age:18 isMan:true sex:男通过上面的例子,可以看出通过使用optString()可以将整形转化为字符串。而对于sex,因为该字段没有,会为其付默认值。解决了抛出异常的问题。
深入进去,看一下他们的源码。
optString() // optString 默认调用了optString(key, ""); public String optString(String key) { return this.optString(key, ""); } //如果是null,返回默认值,否则调用toString方法返回 public String optString(String key, String defaultValue) { Object object = this.opt(key); return NULL.equals(object)?defaultValue:object.toString(); } optBoolean public boolean optBoolean(String key) { return this.optBoolean(key, false); } //实质调用get方法,如果抛出异常,则赋默认值 public boolean optBoolean(String key, boolean defaultValue) { try { return this.getBoolean(key); } catch (Exception var4) { return defaultValue; } }get()取值不正确会抛出异常,必须用try catch或者throw包起
opt()取值不正确则会试图进行转化或者输出友好值,不会抛出异常
如上,介绍了Android原生的解析,但在实际开发中,为了提高效率,往往使用第三方解析类库,而下面我们将进入到第三方类库的使用。
GSON 解析Gson解析是google 提供的快速json解析库。其和原生的相比,最大的优点是可以按照bean类对数据进行解析。
因为其属于第三方库,所以我们需要导包,如果使用的是AndroidStudio,直接搜索gson导入即可。
使用的是eclipse的话,则在该地址下载,将jar包加入到工程中。
Gson 解析单一实体类对象还是上面的数据格式
{ "user": { "name": "alex", "age": "18", "isMan": true } }对于该数据,我们想要获取的是user中的字段值,首先定义User实体类,注意:该类名没有要求,随便命名。
public class User { private String name; private int age; private boolean isMan; private String sex; }有两点需要注意:
类中成员变量名一定要和json数据中字段一一对应。 多添加了sex字段,测试当获取的字段不存在时的情况。 //使用Gson解析实体类对象 //1, 获取对应实体类对象的字符串,当前为user的值。 String userJson = new JSONObject(json).getJSONObject("user").toString(); //userJson = "{\"name\":\"alex\",\"age\":18,\"isMan\":true}"; //2 , 创建Gson 对象 Gson gson = new Gson(); // 3, fromJson 解析 User user = gson.fromJson(userJson, User.class); System.out.println(user); User{name='alex', age=18, isMan=true, sex='null'}关键方法为fromJson,该方法第一个参数为需要解析的json数据,第二个参数为需要解析成的目标对象的class。
因为该例子比较特殊,当前数据中user中的值不是最外层的json数据,他被包裹起来了,所以我们先把他剥开,获取user对应的值。
有时候,返回的数据中字段值和我们前端的命名习惯不同,导致字段无法一一对应。如果我们的数据修改成了如下样式
{ "user": { "name": "alex", "age": "18", "is_man": true } }字段值得到了修改,isMan-》is_man,如果我们实体类也改成该字段名,那么就不符合命名规范了。
在Gson中有如下注解@SerializedName
@SerializedName("is_man") private boolean isMan;这样就解决了问题。
还有一种情况,如果对于该字段,有的地方使用is_man,有的地方使用is_Man,甚至还有isMan。那么我们因为三个字段名的不同建立三个实体类,很是蛋疼。
@SerializedName(value = "is_man",alternate = {"is_Man","isMan"}) private boolean isMan;当然,如果这三个字段同时出现时,会取最后一次出现的对应值进行赋值。
Gson 解析数组型实体类对象对于例子,我们修改一下
{ "user": [ { "name": "alex", "age": "18", "is_man": true }, { "name": "mahao", "age": "16", "is_man": true } ] }user中所对应的值不再是一个JSONObject,而是JSONArray类型。
public static void parserArray(){ String json = "{\"user\":[{\"name\":\"alex\",\"age\":18,\"isMan\":true},{\"name\":\"mahao\",\"age\":16,\"isMan\":true}]}"; //1, 获取对应实体类对象的字符串,当前为user的值。 String userJson = new JSONObject(json).getJSONArray("user").toString(); //2 ,创建Gson 对象 Gson gson = new Gson(); //3, 获取user 数组 User[] users = gson.fromJson(userJson, User[].class); System.out.println(users[1]); }最终解析出了User[]数组。
平常我们往往使用List存储数据。
第三步改成了如下代码
List users = gson.fromJson(userJson, List.class);报错!!! 因为第二个参数的字节码,实际为List.class ,User被忽略了。 泛型擦除
Gson为我们提供了另一个方法解决该问题
List users = gson.fromJson(userJson,new TypeToken>(){}.getType()); System.out.println(users.get(1)); 通过Gson 构造json数据 根据实体类对象生成json 数据。 public static void writeBeanJson(){ //1 构造gson 对象 Gson gson = new Gson(); //2 构造对象 User user = new User(); user.setName("lala"); user.setAge(20); // 3 生成json 数据 String json = gson.toJson(user); System.out.println(json); } {"name":"lala","age":20,"is_man":false}如果实体类中为null或空字符串,则该字段不会被转化。当然也可以通过GsonBuilder设置,后面会提到。
自定义json数据。