Gson学习-1

作者: 盼旺 | 来源:发表于2019-09-19 12:51 被阅读0次

    原文地址:https://www.jianshu.com/p/e740196225a4

    简介:

    JSON 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成
    Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等
    注意点
    1.一个对象以 {左括号 开始,}右括号 结束
    2.一个数组以[左中括号 开始,]右中括号 结束
    3.字符串是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义引号。

    集成Gson

    <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
       <version>2.8.5</version>
    </dependency>
    

    一、Gson的基本用法

    Gson提供了fromJson()toJson()两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。

    下文学习
    Gson.toJson(Object);
    Gson.fromJson(Reader,Class);
    Gson.fromJson(String,Class);
    Gson.fromJson(Reader,Type);
    Gson.fromJson(String,Type);
    

    基本数据类型的解析

    Gson gson = new Gson();
    int i = gson.fromJson("100", int.class);              //100
    double d = gson.fromJson("\"99.99\"", double.class);  //99.99
    boolean b = gson.fromJson("true", boolean.class);     // true
    String str = gson.fromJson("String", String.class);   // String
    

    第二行为一个字符串
    基本数据类型的生成

    Gson gson = new Gson();
    String jsonNumber = gson.toJson(100);       // 100
    String jsonBoolean = gson.toJson(false);    // false
    String jsonString = gson.toJson("String"); //"String"
    

    普通java对象的生成与解析

    public class Student {
        public String name;
        public int age;
        public String emailAddress;
        //省略其他
        public Student(String name, int age, String emailAddress) {
            this.name = name;
            this.age = age;
            this.emailAddress = emailAddress;
        }
        public Student() {
        }
    }
            Gson gson = new Gson();
            Student student = new Student("星星",22,"1354534s4d@qq.com");
            String jsonObject = gson.toJson(student);
            System.out.println(jsonObject);
            //{"name":"星星","age":22,"emailAddress":"1354534s4d@qq.com"}
    

    二、属性重命名 @SerializedName 注解的使用

    默认的json的字段和值是和类中名称和类型是一一对应的
    现在想实现

    {"name":"星星","age":22,"emailAddress":"1354534s4d@qq.com"}
    不想要这样的email,需求下面的样式
    {"name":"星星","age":22,"email_address":"1354534s4d@qq.com"}
    

    SerializedName注解的使用

    1.@SerializedName("email_address")
    public String emailAddress;
    解释为把emailAddress变成email_address
    上面的代码生成的json就是下面这样的了
    {"name":"星星","age":22,"email_address":"1354534s4d@qq.com"}
    
    2.@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
    一个String,一个String数组表示备选属性名
    解释为json生成类的时候,遇到email或者email_address都变成emailAddress
    

    三、Gson中使用泛型

    1.JSON解析字数组
    一般有两种方式:使用数组,使用List。List对于增删都是比较方便的,所以实际使用是还是List比较多。

    使用数组
            Gson gson = new Gson();
            String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
            String[] strings = gson.fromJson(arraystr, String[].class);
            System.out.println(Arrays.toString(strings));
            //[Android, Java, PHP]
    

    但对于List将上面的代码中的 String[].class直接改为 List<String>.class是行不通的。对于Java来说List<String>List<User> 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除

    为了解决的上面的问题,Gson为我们提供了TypeToken来实现对泛型的支持,所以当我们希望使用将以上的数据解析为List<String>时需要这样写。

            Gson gson = new Gson();
            String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
            List<String> stringList = gson.fromJson(arraystr, new TypeToken<List<String>>() {}.getType());
            System.out.println(stringList);
            //[Android, Java, PHP]
    

    \color{red}{注意}
    TypeToken的构造方法是protected修饰的,所以上面才会写成
    new TypeToken<List<String>>() {}.getType()
    而不是
    new TypeToken<List<String>>().getType()
    2.当返回的数据分为两类或者更多比如:

    data是数组
    {"code":"0","message":"success","data":[]}
    data是对象
    {"code":"0","message":"success","data":{}}
    

    现在怎么设计这个大的对象呢?

    public class Result<T> {
        public int code;
        public String message;
        public T data;
    }
    

    这样用泛型代替
    那么对于data字段是User时则可以写为 Result<User> ,当是个列表的时候为 Result<List<User>>,其它同理。

    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    
    import java.lang.reflect.Type;
    import java.util.*;
    public class Main {
        public static void main(String[] args) {
            Gson gson = new Gson();
    //        data是数组
           String str1 =  "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"星星1\",\"age\":\"22\",\"email\":\"5456s45@qq.com\"},{\"name\":\"星星2\",\"age\":\"22\",\"email\":\"5456s45@qq.com\"}]}";
    //        data是对象
            String str2 = "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"星星\",\"age\":\"22\",\"email\":\"5456s45@qq.com\"}}";
            //data是数组
            Type userListType = new TypeToken<Result<List<User>>>(){}.getType();
            Result<List<User>> userListResult = gson.fromJson(str1,userListType);
            System.out.println(gson.toJson(userListResult));
    //{"code":0,"message":"success","data":[{"name":"星星1","age":22,"email":"5456s45@qq.com"},{"name":"星星2","age":22,"email":"5456s45@qq.com"}]}
            //data是对象
            Type userType = new TypeToken<Result<User>>(){}.getType();
            Result<User> userResult = gson.fromJson(str2,userType);
            System.out.println(gson.toJson(userResult));
    //{"code":0,"message":"success","data":{"name":"星星","age":22,"email":"5456s45@qq.com"}}
        }
    }
    

    当data数组里面里面为字符串的时候:

    String str1 =  "{\"code\":\"0\",\"message\":\"success\",\"data\":[\"123\",\"456\"]}";
    Type userListType = new TypeToken<Result<List<String>>>(){}.getType();
    Result<List<String>> userListResult = gson.fromJson(str1,userListType);
    System.out.println(gson.toJson(userListResult));
    尝试为List<Interger> 失败
    

    四、解析如下奇葩字符串

    {
      0={"name":"星星1","age":22,"email":"5456s45@qq.com"},
      1={"name":"星星2","age":22,"email":"5456s45@qq.com"},
      2={"name":"星星3","age":22,"email":"5456s45@qq.com"}
    }
    

    这里用到自定义反序列化

    利用JsonDeserializer 接口只需要实现一个反序列化方法deserialize 就足够了
    1.定义解析成的类型User2

    public class User2 {
        Map<Integer, Data> map;
        class Data {
            public String name;
            public int age;
            public String email;
    
            @Override
            public String toString() {
                return "Data{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", email='" + email + '\'' +
                        '}';
            }
        }
    }
    

    2.定义自定义的反序列化

    public class MapDeserializer implements JsonDeserializer<User2> {
    //    当请求将JSON内容反序列成java类型对象的时候,该方法将会被调用。然后,会返回一个
    //    由方法自己构造的对象实例。
    //    需要注意的是,当JSON为null的时候,该方法该不会被调用,因此,方法不需要去check 该值是否为null
    //参数1 是json字符串 参数2 是返回的类型 参数3传递给自定义反序列化器的上下文 抛出错误如果解析的json字符串不包括指定的类型
        @Override
        public User2 deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
    //        将指定成员作为JsonObject获取的便捷方法。
            JsonObject jsonObject=jsonElement.getAsJsonObject();
    //        返回此对象的一组成员。
            Set<Map.Entry<String,JsonElement>> set=jsonObject.entrySet();
    //        定义map
            Map<Integer, User2.Data> map = new HashMap<>();
    //        遍历set
            for(Map.Entry<String,JsonElement> s : set){
    //            定义一个user2的data
                User2.Data data = jsonDeserializationContext.deserialize(s.getValue().getAsJsonObject(), User2.Data.class);
    //            入map s.getKey() 和 data
                map.put(Integer.valueOf(s.getKey()),data);
            }
    //        最后返回一个整体User2
            User2 user2 = new User2();
            user2.map=map;
            return user2;
        }
    }
    

    3.注册自定义的反序列化并使用

    public static void main(String[] args) {
    
            String str = "{0={\"name\":\"星星1\",\"age\":22,\"email\":\"5456s45@qq.com\"},1={\"name\":\"星星2\",\"age\":22,\"email\":\"5456s45@qq.com\"},2={\"name\":\"星星3\",\"age\":22,\"email\":\"5456s45@qq.com\"}}";
            User2 user2 = new User2();
            Gson gson = new GsonBuilder()
                    .registerTypeAdapter(User2.class, new MapDeserializer())//为User2注册MapDeserializer
                    .create();
            user2 = gson.fromJson(str,User2.class);
            System.out.println(user2.map.get(1));
    //        Data{name='星星2', age=22, email='5456s45@qq.com'}
        }
    

    相关文章

      网友评论

        本文标题:Gson学习-1

        本文链接:https://www.haomeiwen.com/subject/zibkuctx.html