美文网首页
Gson学习-3

Gson学习-3

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

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

主要内容

1.字段过滤的几种方法
2.POJO类与JSON的字段映射规则

一、字段过滤的几种方法

以一个商品分类Category为例。

{
  "id": 1,
  "name": "电脑",
  "children": [
    {
      "id": 100,
      "name": "笔记本"
    },
    {
      "id": 101,
      "name": "台式机"
    }
  ]
}

一个大分类,可以有很多小分类,那么显然我们在设计Category类时Category本身既可以是大分类,也可以是小分类。

public class Category {
    public int id;
    public String name;
    public List<Category> children;
}

但是为了处理业务,我们还需要在子分类中保存父分类,最终会变成下面的情况

public class Category {
    public int id;
    public String name;
    public List<Category> children;
    //因业务需要增加,但并不需要序列化
    public Category parent; 
}

但是上面的parent字段是因业务需要增加的,那么在序列化是并不需要,所以在序列化时就必须将其排除,那么在Gson中如何排除符合条件的字段呢?
①基于@Expose注解
使用方法: 简单说来就是需要导出的字段上加上@Expose 注解,不导出的字段不加。注意是不导出的不加。

@Expose //默认序列化和反序列化都都生效
@Expose(deserialize = true,serialize = true) //序列化和反序列化都都生效,等价于上一条
@Expose(deserialize = true,serialize = false) //反序列化时生效
@Expose(deserialize = false,serialize = true) //序列化时生效
@Expose(deserialize = false,serialize = false) // 和不写注解一样

上面的例子变成下面这样

public class Category {
    @Expose public int id;
    @Expose public String name;
    @Expose public List<Category> children;
    //不需要序列化,所以不加 @Expose 注解,
    //等价于 @Expose(deserialize = false,serialize = false)
    public Category parent; 
}

使用Gson时注意配置。

Gson gson = new GsonBuilder()
        .excludeFieldsWithoutExposeAnnotation()
        .create();
gson.toJson(category);
配置Gson以排除所有字段,使其不考虑没有Expose批注的序列化或反序列化。

完整例子

public class User {
   @Expose
   public String name;
   @Expose
   public int age;
    public String email;
    //省略其他
    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
    public User() {
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", email='" + email + '\'' +
                '}';
    }
}
主函数
        String str = "{\"name\":\"星星\",\"age\":22,\"email\":\"5456s45@qq.com\"}";
        Gson gson = new GsonBuilder()
                            .excludeFieldsWithoutExposeAnnotation()
                            .create();
        User user = gson.fromJson(str,User.class);
        System.out.println(user.toString());
        //User{name='星星', age=22, email='null'}

②基于版本
Gson在对基于版本的字段导出提供了两个注解 @Since@Until,和GsonBuilder.setVersion(Double)配合使用。@Since@Until都接收一个Double值。
使用方法:当前版本(GsonBuilder中设置的版本) 大于等于Since的值时该字段导出,小于Until的值时该该字段导出。

class SinceUntilSample {
    @Since(4)//大于等于4有效
    public String since;
    @Until(5)//小于5有效
    public String until;
}

public void sineUtilTest(double version){
        SinceUntilSample sinceUntilSample = new SinceUntilSample();
        sinceUntilSample.since = "since";
        sinceUntilSample.until = "until";
        Gson gson = new GsonBuilder().setVersion(version).create();
        System.out.println(gson.toJson(sinceUntilSample));
}
//当version <4时,结果:{"until":"until"}
//当version >=4 && version <5时,结果:{"since":"since","until":"until"}
//当version >=5时,结果:{"since":"since"}

注:当一个字段被@Since @Until俩个同时注解时,需两者同时满足条件。
③基于访问修饰符
什么是修饰符? public、static 、final、private、protected这些就是,所以这种方式也是比较特殊的。

class ModifierSample {
    final String finalField = "final";
    static String staticField = "static";
    public String publicField = "public";
    protected String protectedField = "protected";
    String defaultField = "default";
    private String privateField = "private";
}

使用GsonBuilder.excludeFieldsWithModifiers构建gson,支持int的可变参数,值由java.lang.reflect.Modifier提供,下面的程序排除了privatefinalstatic 类型。

ModifierSample modifierSample = new ModifierSample();
Gson gson = new GsonBuilder()
        .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE)
        .create();
System.out.println(gson.toJson(modifierSample));
// 结果:{"publicField":"public","protectedField":"protected","defaultField":"default"}

④基于策略(自定义规则)
基于策略是利用Gson提供的ExclusionStrategy接口,同样需要使用GsonBuilder,相关API 2个,分别是addSerializationExclusionStrategyaddDeserializationExclusionStrategy 分别针对序列化和反序化时。这里以序列化为例。

Gson gson = new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                // 这里作判断,决定要不要排除该字段,return true为排除
                if ("finalField".equals(f.getName())) return true; //按字段名排除
                Expose expose = f.getAnnotation(Expose.class); 
                if (expose != null && expose.deserialize() == false) return true; //按注解排除
                return false;
            }
            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                // 直接排除某个类 ,return true为排除
                return (clazz == int.class || clazz == Integer.class);
            }
        })
        .create();

强大啊!
完整例子反序列化

String str = "{\"name\":\"星星\",\"age\":22,\"email\":\"5456s45@qq.com\"}";
Gson gson = new GsonBuilder()
                    .addDeserializationExclusionStrategy(new ExclusionStrategy() {
                        @Override
                        public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                            //按字段排除return true为排除
                            if("email".equals(fieldAttributes.getName())){
                                return true;
                            }
                            return false;
                        }

                        @Override
                        public boolean shouldSkipClass(Class<?> aClass) {
                            //按雷系排除return true为排除
                            if(aClass==int.class){
                                return true;
                            }
                            return false;
                        }
                    })
                    .create();
User user = gson.fromJson(str,User.class);
System.out.println(user.toString());
//User{name='星星', age=0, email='null'}

二、 POJO类与JSON的字段映射规则

前面介绍了@SerializedName这个注解的使用
这里学习setFieldNamingPolicy 采用默认类的策略setFieldNamingStrategy 采用自定义的策略的使用

默认策略有

IDENTITY 在Gson中使用此命名策略将确保字段名称保持不变。
LOWER_CASE_WITH_DASHES 在Gson中使用此命名策略会将Java字段名称从其camel cased表单修改为小写字段名称,其中每个单词用短划线( - )分隔。
LOWER_CASE_WITH_DOTS 在Gson中使用此命名策略会将Java字段名称从其camel cased表单修改为小写字段名称,其中每个单词用点(.)分隔。
LOWER_CASE_WITH_UNDERSCORES 在Gson中使用此命名策略会将Java字段名称从其camel cased表单修改为小写字段名称,其中每个单词由下划线(_)分隔。
UPPER_CAMEL_CASE 在Gson中使用此命名策略将确保Java字段名称的第一个“字母”在序列化为其JSON格式时大写。
UPPER_CAMEL_CASE_WITH_SPACES 在Gson中使用此命名策略将确保Java字段名称的第一个“字母”在序列化为其JSON格式时大写,并且单词将用空格分隔。

举例子

[IDENTITY] : 返回本身的格式
 user        --->     user
 userName    --->     userNmae
 [UPPER_CAMEL_CASE] -- 首个字母大写
 someFieldName --->  SomeFieldName
 _someFieldName ---> _SomeFieldName
 [UPPER_CAMEL_CASE_WITH_SPACES] -- 以空格隔开
 someFieldName ---> Some Field Name
 _someFieldName ---> _Some Field Name
 [LOWER_CASE_WITH_UNDERSCORES] -- 以下划线隔开
 someFieldName ---> some_field_name
 _someFieldName ---> _some_field_name
 aStringField ---> a_string_field
 aURL ---> a_u_r_l
 [LOWER_CASE_WITH_DASHES]  -- 以中间线隔开
 someFieldName ---> some-field-name
 _someFieldName ---> _some-field-name
aStringField ---> a-string-field
aURL ---> a-u-r-l
[LOWER_CASE_WITH_DOTS]  ---- 以点号隔开
someFieldName ---> some.field.name
_someFieldName ---> _some.field.name
aStringField ---> a.string.field
aURL ---> a.u.r.l   
public class Model {
    public String userName;
    public String emailAddress;

    public Model() {
    }

    public Model(String userName, String emailAddress) {
        this.userName = userName;
        this.emailAddress = emailAddress;
    }
}


Model m = new Model("星星","4564wsa@qq.com");
Gson gson = new GsonBuilder()
                    .setFieldNamingPolicy(LOWER_CASE_WITH_DASHES)
                    .create();
System.out.println(gson.toJson(m));
//{"user-name":"星星","email-address":"4564wsa@qq.com"}
String mstr = "{\"user-name\":\"星星\",\"email-address\":\"4564wsa@qq.com\"}";
//IDEA先打双引号,然后复制字符串到里面,自动转义 nice
m = gson.fromJson(mstr,Model.class);
System.out.println(m.toString());
//Model{userName='星星', emailAddress='4564wsa@qq.com'}

自定义策略

Gson gson = new GsonBuilder()
        .setFieldNamingStrategy(new FieldNamingStrategy() {
            @Override
            public String translateName(Field f) {
                //实现自己的规则
                return null;
            }
        })
        .create();
 Gson gson = new GsonBuilder()
                        .setFieldNamingStrategy(new FieldNamingStrategy() {
                            @Override
                            public String translateName(Field field) {
                                if(field.getName().equals("name")){
                                    return "NAME";
                                }
                                return field.getName();
                            }
                        })
                        .create();
User user = new User("星星",22,"465464q@qq.com");
gson.toJson(user,System.out);//{"NAME":"星星","age":22,"email":"465464q@qq.com"}

注意: 前面介绍的@SerializedName注解拥有最高优先级,在加有@SerializedName注解的字段上FieldNamingStrategy不生效!

相关文章

  • Gson学习-3

    原文地址:https://www.jianshu.com/p/e740196225a4 主要内容 1.字段过滤的几...

  • Tools

    完全理解Gson(3):Gson反序列化 完全理解Gson(2):Gson序列化 完全理解Gson(1):简单入门...

  • Gson 系列文章

    gson教程 1、Gson - Java-JSON 序列化和反序列化入门2、Gson - 映射嵌套对象3、Gson...

  • Gson用户使用文档

    1.概述2.Gson的目标3.Gson的性能和扩展性4.Gson的使用者5.如何使用Gson 通过Maven来使用...

  • Gson解析JSON

    1. 开始 构建maven项目 实体类 2. gson解析对象 3. gson反序列化 4、Gson高级使用 1、...

  • Gson教程 Apache POI教程 Guava教程Apac

    Gson教程 Gson概述Gson环境设置Gson第一个应用Gson classGson对象序列化Gson数据绑定...

  • list集合转换为json

    //后台Gson gson=new Gson();String json=gson.toJson(集合, new ...

  • Gson用户指南(中文翻译)

    为了更好的学习Gson,特将Gson User Guide翻译如下。由于本人英文水平有限,如有错误,还请指正,谢谢...

  • GSON 解析 JSON

    GSON JSON 介绍 Gson 下载 Gson 解析 和 格式化Gson 格式化Gson 解析 解析asset...

  • 2018-01-11

    Gson解析复杂json数据常用的两种解析方式 Gson gson = new Gson(); 1.gson.fr...

网友评论

      本文标题:Gson学习-3

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