gson笔记

<!-- maven gson -->
<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
	<version>2.3.1</version>
</dependency>
//Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。

// 1、Gson如何使用。
// Gson对象主要有两个方法
//     fromJson() => java类型 解析来自        json。
//     toJson()   => java类型 生成(序列化成)  json。
// 2、如何获取Gson对象
// 两种方式
//     new Gson()
//     new GsonBuilder().create()
// 3、两种方式获取gson对象的区别
// 利用GsonBuilder创建gson对象时,可以增加一些特殊处理,应该说是比第一种方式功能更强大

基本数据类型
    基本数据类型的解析
    Gson gson = new Gson();
    int i = gson.fromJson("100", int.class);              //100
    double d = gson.fromJson("\"99.99\"", double.class);  //99.99 将字符串的99.99转成double型
    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"

POJO类的生成与解析//
    public class User {
        private int id;
        private String name;
        private int age;
        private String emailAddress;
        //省略Constructor、Getter、Setter、toString()
    }

     1.将bean转换成Json字符串:
    Gson gson = new Gson();
    User user = new User(1,"李李",22,"ll@orz.com");
    String json = gson.toJson(user);
    // {"id":1,"name":"李李","age":24,"emailAddress":"ll@orz.com"}

     2.将Json字符串转换成对象:
    String jsonStr = "{\"id\":1,\"name\":\"李李\",\"age\":24,\"birthDay\":\"Jun 22,\"emailAddress\":\"ll@orz.com\"}";
    Gson gson = new Gson();
    User user = gson.fromJson(jsonString, User.class);
     3.将Json字符串转换成JsonObject对象:
    JsonObject jsonObject = new JsonParser().parse(jsonstr).getAsJsonObject();
     4.将JsonArray类型的Json字符串解析成JsonArray对象方法:
    String jsonArr = "[\"Android\",\"Java\",\"PHP\"]";
    JsonArray Jarray = new JsonParser().parse(jsonArr).getAsJsonArray();
    ArrayList<String> als = new ArrayList<String>();
    Gson gson = new Gson();
    for(JsonElement obj : Jarray ){
        String str = gson.fromJson( obj , String.class);
        als.add(str);
    }
    //或者
    String jsonA = "[{\"username\":\"test\"},{\"username\":\"test2\"}]";
    System.out.println(new JsonParser().parse(jsonA).getAsJsonArray().get(0).getAsJsonObject().get("username").getAsString());

     5.获取JsonObject中指定key值对应的JsonArray对象:
    String jsonS= "{\"pids\":[\"1\",\"2\",\"3\"]}";
    System.out.println(new JsonParser().parse(jsonS).getAsJsonObject().getAsJsonArray("pids").get(0).getAsString());

带泛型的List之间的转化//
    List<user> list = new ArrayList<User>();
    list.add(new User(1,"李李",21,"ll@orz.com"));
    list.add(new User(2,"康康",22,"kk@orz.com"));
    list.add(new User(3,"宝宝",23,"bb@orz.com"));

     带泛型的list转化为json
    String s1 = gson.toJson(list);

     json转为带泛型的list
    List<Student> arrLs = gson.fromJson(s1, new TypeToken<List<Student>>(){}.getType());
    for (User u : arrLs) {
        System.out.println(u);
    }

 Gson注解///
    /// @SerializedName 使用 注解 给 属性重命名
    //期望的json格式
    {"id":1,"name":"李李","age":24,"emailAddress":"ll@orz.comm"}
    //实际
    {"id":1,"name":"李李","age":24,"email_address":"ll@orz.com"}
    //对于json中email_address这个属性对应POJO的属性则变成:
        @SerializedName("email_address")
        public String emailAddress;
    //有下面三种情况那怎么办?
    {"id":1,"name":"李李","age":24,"emailAddress":"ll@orz.com"}
    {"id":1,"name":"李李","age":24,"email_address":"ll@orz.com"}
    {"id":1,"name":"李李","age":24,"email":"ll@orz.com"}
    //为POJO字段提供备选属性名
    //SerializedName注解提供了两个属性,还有一个属性alternate,接收一个String数组。
    //注:alternate需要2.4版本
    @SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
    public String emailAddress;
    //当上面的三个属性(email_address、email、emailAddress)都中出现任意一个时均可以得到正确的结果。
    //注:当多种情况同时出时,以最后一个出现的值为准。
    Gson gson = new Gson();
    String json = "{\"name\":\"李李\",\"age\":24,\"emailAddress\":\"ll@orz.com\",\"email\":\"ll@orz.com\",\"email_address\":\"ll@orz.com\"}";
    User user = gson.fromJson(json, User.class);
    System.out.println(user.emailAddress); // ll@orz.com

GsonBuilder/
     有时候我们不需要把实体的所有属性都导出,只想把一部分属性导出为Json.
     有时候我们的实体类会随着版本的升级而修改.
     有时候我们想对输出的json默认排好格式.
     ... ...
    工具类
    public class Java2Json {
        public static String obj2JsonWithGson(Object obj) {
            return new Gson().toJson(obj);
        }
        public static String obj2JsonWithGson(Object obj,Type type) {
            return new Gson().toJson(obj,type);
        }
        @SuppressWarnings("unchecked")
        public static String obj2JsonWithGson(List list) {
            return new Gson().toJson(list);
        }
        @SuppressWarnings("unchecked")
        public static String obj2JsonWithGson(List list,Type type) {
            return new Gson().toJson(list,type);
        }

        public static String obj2JsonWithGsonBuilder(Object obj) {
            Gson gson=new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy()).serializeNulls().create();
            return gson.toJson(obj);
        }
        public static String toJsonWithGsonBuilder(Object obj,Type type) {
            Gson gson=new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy()).serializeNulls().create();
            return gson.toJson(obj,type);
        }
        @SuppressWarnings("unchecked")
        public static String toJsonWithGsonBuilder(List list) {
            Gson gson=new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy()).serializeNulls().create();
            return gson.toJson(list);
        }
        @SuppressWarnings("unchecked")
        public static String toJsonWithGsonBuilder(List list,Type type) {
            Gson gson=new GsonBuilder().setExclusionStrategies(new MyExclusionStrategy()).serializeNulls().create();
            return gson.toJson(list,type);
        }
    }
    //参数中的type如何创建
    //(1)普通对象,如User user=new User();得到type方式,user.class
    //(2)复杂对象,如List<User> users=new ArrayList<User>();得到type方式,
    //     new TypeToken<List<User>>(){}.getType()
    //GsonBuilder有哪些优势
    //(1)可以采用注解的方式,个性化定制需要序列化和方序列化的字段,如在字段前面添加@Expose注解,当采用GsonBuilder.excludeFieldsWithoutExposeAnnotation()方法时,没有该注解的字段将被排除在外。其他注解还有@SerializeName、@Since和@Until,具体意思参见Gson API文档
    //(2)定制自己的注解和排除策略。如上述代码中实现ExclusionStrategy接口的类 MyExclusionStrategy,代码如下:
    import com.google.gson.ExclusionStrategy;
    import com.google.gson.FieldAttributes;
    public class MyExclusionStrategy implements ExclusionStrategy {
        private final Class<?> typeToSkip;
        public MyExclusionStrategy(){
            this.typeToSkip=null;
        }
        public MyExclusionStrategy(Class<?> typeToSkip) {
            this.typeToSkip = typeToSkip;
        }
        public boolean shouldSkipClass(Class<?> clazz) {
            return (clazz == typeToSkip);
        }
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getAnnotation(NotSerialize.class) != null;
        }
    }
    自己的注解接口NotSerialize,代码如下
    /*import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface NotSerialize {
    }

    这时,我们用的时候,只要在不序列化的字段前面加上@NotSerialize注解(比如说密码字段,保证其安全性就没必要序列化出来了),采用new GsonBuilder().setExclusionStrategies()方法设置排除策略创建的Gson对象时,该字段将不再被序列化  */
     实体类:
    public class User {
        private int id;
        //当采用GsonBuilder.excludeFieldsWithoutExposeAnnotation()方法创建Gson时这个注解才起作用,
        //没有该注解的字段将被排除在外,默认情况下序列化和反序列化都会使用
        @Expose
        @SerializedName("name") //序列化时会把userName字段名映射为name
        private String userName;
        //序列化时使用,反序列化不使用该字段,默认都等于true
        @Expose(serialize=true,deserialize=false)
        private String  userPwd;
        //@Since(1.1) //标记这个字段只有在1.1“版本”以上才会序列化和反序列化
        private int age;
        @Expose
        @SerializedName("bir")
        private Date birthDay;
        //省略Constructor、Getter、Setter、toString()
    }
     测试:
    //注意这里的Gson的构建方式为GsonBuilder,区别于Gson gson = new Gson();
        Gson gson = new GsonBuilder()
        .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
        .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
        .serializeNulls() //当需要序列化的属性值为空时,采用null映射,否则生成的json会把该字段省略
        .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//时间转化为特定格式
        .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//把字段首字母大写,注:实体字段上使用了@SerializedName注解的不会生效.
        .setPrettyPrinting() //对json结果格式化.
        .setVersion(1.0)    //有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.
                            //@Since(版本号)能完美地实现这个功能.还的字段可能,随着版本的升级而删除,那么
                            //@Until(版本号)也能实现这个功能,GsonBuilder.setVersion(double)方法需要调用.
        .create();

Gson中使用泛型///
//上面了解的JSON中的Number、boolean、Object和String,现在说一下Array。
//例:JSON字符串数组
    ["Android","Java","PHP"]
    //当我们要通过Gson解析这个json时,一般有两种方式:使用数组,使用List。而List对于增删都是比较方便的,所以实际使用是还是List比较多。

    //数组比较简单
    Gson gson = new Gson();
    String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
    String[] strings = gson.fromJson(jsonArray, String[].class);
    //但对于List将上面的代码中的 String[].class 直接改为 List<String>.class 是行不通的。
    //对于Java来说List<String> 和List<User> 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除。

   //Gson为我们提供了TypeToken来实现对泛型的支持,所以当我们希望使用将以上的数据解析为List<String>时需要这样写。
    Gson gson = new Gson();
    String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
    String[] strings = gson.fromJson(jsonArray, String[].class);
    List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
    //注:TypeToken的构造方法是protected修饰的,所以上面才会写成new TypeToken<List<String>>() {}.getType() 而不是  new TypeToken<List<String>>().getType()

    //泛型解析对接口POJO的设计影响
    //泛型的引入可以减少无关的代码,如我现在所在公司接口返回的数据分为两类:

    {"code":"0","message":"success","data":{}}
    {"code":"0","message":"success","data":[]}
    //我们真正需要的data所包含的数据,而code只使用一次,message则几乎不用。如果Gson不支持泛型或不知道Gson支持泛型的同学一定会这么定义POJO。

    public class UserResponse {
        public int code;
        public String message;
        public User data;
    }
    //当其它接口的时候又重新定义一个XXResponse将data的类型改成XX,很明显code,和message被重复定义了多次,通过泛型的话我们可以将code和message字段抽取到一个Result的类中,这样我们只需要编写data字段所对应的POJO即可,更专注于我们的业务逻辑。如:
    public class Result<T> {
        public int code;
        public String message;
        public T data;
    }
    //那么对于data字段是User时则可以写为 Result<User> ,当是个列表的时候为 Result<List<User>>,其它同理。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值