在android里面,肯定离不开数据的解析,对网络请求获取到的json格式进行数据解析,一般使用的比较广泛的有gson、fastJson、jackJson。关于各个工具包的性能比较网络上很多,随便一搜一大把,这里对gson做一个使用的介绍,平时用到的也就这么几个方法,花费了一些时间学习的东西,用的少就容易忘记,是该捡一捡做做记录了。

1.json格式,是用来交换文本形式的数据

2.前两种在google play Top200中使用率57%,可见gson的比重是相当的大。

3.gson使用的下载地址https://github.com/google/gson

4.gson提供了两个直接用于生成和解析json的方法,toJson()实现序列号,fromJson()实现了反序列化。


基本的用法

1.解析基本数据类型--最基本的方式

1,下面可以看到把最基本的数据类型解析出来


public void fromJson(){
        Gson gson = new Gson();
        int i = gson.fromJson("100", int.class);
        double d = gson.fromJson("\"9.9\"", double.class);
        boolean b = gson.fromJson("true", boolean.class);
        String s = gson.fromJson("string",String.class);
        Log.i("gson", " i=" + i + " d=" + d + " b=" + b+" s=" + s);
    }
<pre name="code" class="java">打印的结果是 i=100 d=9.9 b=true s=string



2.生成基本数据类型


public void toJson(){
        Gson gson = new Gson();
        String num = gson.toJson(100);
        String bool = gson.toJson(false);
        String str = gson.toJson("String");
        Log.i("gson", "打印的结果是 num=" + num + " bool=" + bool + " str=" + str);
    }
打印的结果是 num=100 bool=false str="String"

2.下面是稍微复杂一点简单的java对象,生成与解析

1.先写一个简单的bean


public class UserBean {
    
    private String name;
    private int    age;

    public UserBean(String name, int age) {
        this.name = name;
        this.age = age;
    }
}


2,生成json

UserBean bean = new UserBean("赵子龙",100);
 String toJson = gson.toJson(bean);
 Log.i("gson", "打印的结果是 toJson=" + toJson);


3,通过ben生成了json格式的数据

打印的结果是 toJson={"age":100,"name":"赵子龙"}



3.通过上面的bean将生成的json数据解析出来

1.复写bean的toString方法

public class UserBean {

    private String name;
    private int    age;

    public UserBean(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}



2。json生成bean对象



String fromJson = "{\"name\":\"刘玄德\",\"age\":33}";
 UserBean bean = gson.fromJson(fromJson, UserBean.class);
 Log.i("gson", "打印的结果是 " + bean.toString());


3.结果

打印的结果是 UserBean{name='刘玄德', age=33}


4.这个解析也可以通过手动来完成,不过我相信也没有人去这样做。

1.方式介绍


UserBean bean2 = new UserBean();
        String fromJson2 = "{\"name\":\"刘玄德2\",\"age\":33}";
        JsonReader reader = new JsonReader(new StringReader(fromJson2));
        try {
            reader.beginObject();
            while (reader.hasNext()){
                String s1 = reader.nextName();
                switch (s1) {
                    case "name":
                        bean2.name = reader.nextString();
                        break;
                    case "age":
                        bean2.age = reader.nextInt();
                        break;
                }
            }
            reader.endObject();
            Log.i("gson", "打印的结果是 bean2= " + bean2.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }

2.结果


打印的结果是 bean2= UserBean{name='刘玄德2', age=33}


5。既然能手动解析json那么也可以手动进行生成json

1.方式


<span >	</span>JsonWriter jsonWriter = new JsonWriter(new LogWriter("gson"));
        try {
            jsonWriter.beginObject().name("name").value("赵子龙")
                                    .name("age").value(100).endObject();
            jsonWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }


2.结果


{"name":"赵子龙","age":100}



6.接下来是注解的使用

1.不知道看到这里的例子有没有疑惑?在第一个例子中的double转换的时候有没有发现9.9也是字符串。也就是String类型,其实那里应该是这样的写的


double d = gson.fromJson("\"9.9\"", double.class);


那么为什么写成字符串也是可以的呢?是因为它又一定的容错机制,但是有时候这个机制并不可行,比如我们把bean再加一个字段email_address,这时我们所期望的json应该是


{"name":"赵子龙", "age":"100", "email_address":"utmoi@163.com"}

android中的名字都是驼峰的写法,但是这个json字段的下划线拼接的,这是的问题可以使用注解得到很好的解决



2.使用注解



public class UserBean {

    public String name;
    public int    age;

    @SerializedName("email_address") //注解方式
    public String emailAddress;
    
    public UserBean(String name, int age , String emailAddress) {
        this.name = name;
        this.age = age;
        this.emailAddress = emailAddress;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


这样就满足了命名规范,那么如果要是再有另一种情况怎么办?也是有解决的办法,把注解变成数组形式

public class UserBean {

    public String name;
    public int    age;

    @SerializedName(value = "emailAddress",alternate = {"email" , "email_address"})
    public String emailAddress;
    
    public UserBean(String name, int age , String emailAddress) {
        this.name = name;
        this.age = age;
        this.emailAddress = emailAddress;
    }
    
}

这样无论有几种形式就全能搞定。

3.多种情况同时出现的时候,以多种注解情况举例子


Gson gson = new Gson(); //多个注解地址同时出现的情况以最后一个位准
 String fromJson3 = "{\"name\":\"刘玄德3\",\"age\":33,\"emailAddress\":\"utmoi@163.com\",\"email\":\"utmoi@1634.com\"}";
 UserBean bean = gson.fromJson(fromJson3, UserBean.class);
 Log.i("gson" , bean.toString());


4.结果

UserBean{name='刘玄德3', age=33, emailAddress='utmoi@1634.com'}


是以最后一个结果为准


7.下面在看一个方法,也是类似上面注解这种,映射规则的GsonBuilder.setFieldNamingPloicy()要配合枚举使用,同样是上面的userbean,把注解去掉,使用gsonBuilder

1.方式介绍


Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
 UserBean userBean = new UserBean("赵子龙",100,"utmoi@163.com");
 String toJson = gson.toJson(userBean);
 Log.i("gson", "打印的结果是 toJson= " + toJson);


2.结果


打印的结果是 toJson= {"age":100,"email-address":"utmoi@163.com","name":"赵子龙"}

可以看到email的字段key值变了,但是加上了注解,那么就还是原来的样子,说明注解拥有更高的优先级,有注解存在时候这种方式不生效,枚举的类型有几种呢?




答案是有5种。

8.除了有系统枚举的实现方式,还可以自定义实现的
1.方式介绍

Gson gson = new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {
            @Override
            public String translateName(Field f) {
                if("emailAddress".equals(f.getName())){
                    return "email";
                }
                return f.getName();
            }
        }).create();
        UserBean userBean = new UserBean("赵子龙",100,"utmoi@163.com");
        String toJson = gson.toJson(userBean);
        Log.i("gson", "打印的结果是 toJson= " + toJson);


2.打印结果

打印的结果是 toJson= {"age":100,"email":"utmoi@163.com","name":"赵子龙"}


9.复杂一点的解析,带泛型

1.数组的解析,把数组形式的json解析出来

Gson gson = new Gson();
 String jsonArray = "[\"Swift\",\"Java\",\"PHP\"]";
 String[] strings = gson.fromJson(jsonArray, String[].class);
 Log.i("gson", "打印的结果是 strings[0]= " + strings[0] + " strings[1]=" + strings[1] + " strings[2]=" + strings[2]) ;


2.结果

打印的结果是 strings[0]= Swift strings[1]=Java strings[2]=PHP


3.如果不是数组形式,而是List形式,直接把String[].class换成List.class是不行的,因为List<String>和List<UserBean>的字节码文件都是一样的,都是List.class。现在就要用到泛型解析了,当解析List<String>时。


Gson gson = new Gson();
 String jsonArray = "[\"Swift\",\"Java\",\"PHP\"]";
 List<String> strList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
 Log.i("gson", "打印的结果是 strList.get(0)= " + strList.get(0) + " strList.get(1)=" + strList.get(1) + " strList.get(2)=" + strList.get(2)) ;


4。结果


打印的结果是 strList.get(0)= Swift strList.get(1)=Java strList.get(2)=PHP