Json转换神器之Google Gson的使用

Stella981
• 阅读 640

这几天,因为项目的需要,接触了Google的Gson库,发现这个东西很好用,遂记下简单的笔记,供以后参考。至于Gson是干什么的,有什么优点,请各位同学自行百度。

1. 下载Gson

拷贝到项目的lib文件夹中,并将其加入到buildPath中。使用maven的同学,直接在pom中加入以下依赖即可:

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

2. 编写实体类

public class People {
    private String name;
    private int age;
    private boolean setName;

    //ignored setter and getter

    @Override
    public String toString() {
        return "name=" + name + " age=" + age + " setName=" + setName;
    }
}

3. 编写测试类

public class GsonTest {
  public static void main(String[] args) {
    People p = new People();
    p.setAge(20);
    p.setName("People");
    p.setSetName(true);
    Gson gson = new Gson();
    System.out.println(gson.toJson(p));
  }
}

输出结果:

{"name":"People","age":20,"setName":true}

4. 序列化部分字段

以上只是Gson的简单实用,如果我们需要将bool类型的属性setName在转换成json的时候不转换,怎么实现呢? 

4.1 使用Java的transient关键字过滤

让字段不序列化的最简单的方式就是使用Java的关键字transient:

public class People {
    private String name;
    private transient int age;//age is a transient field
    private boolean setName;
}

第3步测试类不变,则会有以下输出:

{"name":"People","setName":true}

4.2 使用Gson自带的Expose注解过滤

此注解作用在属性上,表明当序列化和反序列化的时候,这个属性将会暴露给Gson对象。这个注解只有当创建Gson对象时使用GsonBuilder方式创建并调用了GsonBuilder.excludeFieldsWithoutExposeAnnotation() 方法的时候才有效,否则无效。下面是一个介绍@Expose注解如何使用的例子:

public class People {
    @Expose
    private String name;
    @Expose(serialize = false, deserialize = false)
    private int age;
    private boolean setName;
}

如果你以new Gson()的方式创建Gson对象,toJson()方法和fromJson() 方法在序列化和反序列化的时候将会操作这4个属性。然而,如果你使用

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()

来创建Gson对象,Gson 的 toJson() 和 fromJson() 方法将会排除掉 setName 段,这是因为 setName 字段没有被注解 @Expose 所标记。 这个 Gson 对象同样会排除 age 字段,因为注解@Expose的属性 serialize 被设置成了 false。类似的,Gson也会在反序列化时排除掉 age 字段,因为 deserialize被设置成了 false。

第3步测试类只改变Gson对象的创建过程,则会有以下输出:

{"name":"People"}

4.3 使用Java修饰符过滤

先使用不同的修饰符来修饰字段,

public class People {
    private String name;
    protected int age;//protected field
    private boolean setName; 
}

然后在构造GsonBuilder的时候,可以使用以下方法,来过滤掉被指定修饰符修饰的字段:

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PROTECTED).create();

输出:

{"name":"People","setName":true}

4.4 使用方法名过滤

在Gson的包中找半天,还发现com.google.gson包下面有这么一个接口:ExclusionStrategy ,根据名字可以推断,这个接口是用来设置Gson转换的排除策略的,于是在官网http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html查了一下这个接口,发现只要实现这个接口,并将实现类的对象塞给Gson,在转换成json的时候,Gson就会过滤掉指定的类或者属性。于是有了下面的代码:

public class GsonTest {
  public static void main(String[] args) {
    People p = new People();
    p.setAge(20);
    p.setName("People");
    p.setSetName(true);
    ExclusionStrategy excludeStrategy = new SetterExclusionStrategy();
    Gson gson1 = new GsonBuilder()
      .setExclusionStrategies(excludeStrategy)
      .create();
    Gson gson2 = new Gson();
    String json1 = gson1.toJson(p);
    String json2 = gson2.toJson(p);
    System.out.println(json1);
    System.out.println(json2);

    People p1 = gson1.fromJson(json1, People.class);
    People p2 = gson2.fromJson(json2, People.class);
    System.out.println(p1);
    System.out.println(p2);
  }

  private static class SetterExclusionStrategy implements ExclusionStrategy {
    public boolean shouldSkipClass(Class<?> clazz) {
      return false;
    }
    public boolean shouldSkipField(FieldAttributes f) {
      return f.getName().startsWith("set");
    }
  }
}

原来,Gson对象的创建有两种方式:new Gson()表示使用默认的配置创建一个Gson对象,而如果使用GsonBuilder.create()方法创建,则可以自定义一些设置,这主要是为了使创建的Gson更适合于某些特定的情况。上例中第一段蓝色的代码创建了一个Gson对象,这个对象拥有对以“set”字样开头的属性的过滤的配置(如果需要过滤掉某种类型,则重写ExclusionStrategy接口的shouldSkipClass(Class<?> clazz)方法即可,如果需要过滤掉多种情况,则可以多创建几个ExclusionStrategy的实现类对象,并在创建Gson对象的时候设置进去即可),因此在本例中,将People对象转换成Json的时候,属性setName将被过滤掉。由于json1中没有属性setName,所以将json1反序列化成People对象的时候,boolean类型的setName就没有了值,所以打印的时候取了boolean类型的默认值。于是有了以下结果:

{"name":"People","age":20}
{"name":"People","age":20,"setName":true}
name=People age=20 setName=false
name=People age=20 setName=true

这个解决办法对方法的名称有要求,不是最佳解法。其实我们也可以使用自定义注解,这样的好处是不影响业务逻辑,也不影响方法命名。

4.5 使用自定义注解过滤

首先定义一个自定义的注解Exclude:

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 Exclude {
}

接下来将这个注解标注在指定的字段上:

class People {
    private String name;
    @Exclude
    private int age;
    @Exclude
    private boolean setName;
}

修改测试类,和ExclusionStrategy类:

public class GsonTest {
    public static void main(String[] args) {
        People p = new People();
        p.setAge(20);
        p.setName("People");
        p.setSetName(true);
        ExclusionStrategy excludeStrategy = new AnnotationExclusionStrategy();
        Gson gson1 = new GsonBuilder().setExclusionStrategies(excludeStrategy)
                .create();
        Gson gson2 = new Gson();
        String json1 = gson1.toJson(p);
        String json2 = gson2.toJson(p);
        System.out.println(json1);
        System.out.println(json2);
    }

    private static class AnnotationExclusionStrategy implements ExclusionStrategy {
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {
            return f.getAnnotation(Exclude.class) != null;
        }
    }
}

输出:

{"name":"People"}
{"name":"People","age":20,"setName":true}

5. 使用注解

在com.google.gson.annotation包中,有几个注解Expose, SerializedName, Since和Until,他们各有各的作用,下面使用官方例子介绍常用的注解: 

5.1 SerializedName

此注解作用在属性上,表明这个属性在序列化成Json的时候,需要将名字序列化成注解的value属性指定的值。

这个注解将会覆盖任何的FieldNamingPolicy, 包括默认的命名策略。下面是一个介绍@SerializedName注解如何使用的例子: 

package com.my.gson;

import com.google.gson.annotations.SerializedName;

public class SomeClassWithFields {
    @SerializedName("name")
    private final String someField;
    private final String someOtherField;

    public SomeClassWithFields(String a, String b) {
        this.someField = a;
        this.someOtherField = b;
    }
}

下面的代码展示了序列化上面这个测试类的结果:

SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b");
Gson gson = new Gson();
String jsonRepresentation = gson.toJson(objectToSerialize);
System.out.println(jsonRepresentation);

执行结果是:

{"name":"a","someOtherField":"b"}

由此可见,属性"someField"已经被序列化成了"name"。

注意:在@SerializedName的value中指定的属性名必须为有效的Json属性名。

参考地址:

https://howtoprogram.xyz/2016/10/16/ignore-or-exclude-field-in-gson

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java中常见的json解析方法、库以及性能对比
常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,jsonlib。Gson(项目地址:https://github.com/google/gson)。Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发
Stella981 Stella981
2年前
Gson解析多层嵌套复杂数据
目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),解析速度最快的是Gson,下载地址:https://code.google.com/p/googlegson/(https://www.oschina.net/action/GoToLink?urlhttps
Stella981 Stella981
2年前
Google开源GSON的使用
\谷歌开原项目GitHub地址:https://github.com/google/gson1.新建一个maven项目,引入gson的dependency坐标依赖以及commonsio的坐标:<!处理json格式数据<dependency<groupIdcom.g
Stella981 Stella981
2年前
Gson
Java对象和Json之间的互转,一般用的比较多的两个类库是Jackson和Gson,下面记录一下Gson的学习使用。基础概念: Serialization:序列化,使Java对象到Json字符串的过程。 Deserialization:反序列化,字符串转换成Java对象使用Maven管理Gson,pom.xml导入gson的依赖
Stella981 Stella981
2年前
Gson 数据解析
gson和其他现有javajson类库最大的不同时gson需要序列化的实体类不需要使用annotation来标识需要序列化的字段,同时gson又可以通过使用annotation来灵活配置需要序列化的字段。下面是一个简单的例子:1.public class Person {3.private String name;
Stella981 Stella981
2年前
Gson的学习与使用
Gson介绍:GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。特点:a、快速、高效b、代码量少、简洁c、面向对象d、数据传递和解析方便Gson的pom依赖:<d
Wesley13 Wesley13
2年前
Java操作JSON数据(2)
Gson是Google公司发布的一个开发源码的Java库,可用于将Java对象转换为JSON字符串,也可用于将JSON字符串转换为对应的Java对象。本介绍下Gson的基本使用方法,包括序列化和反序列化;文中所使用到的软件版本:Java1.8.0\_191、Gson2.8.6。1、引入依赖<dependency
Stella981 Stella981
2年前
Gson简要使用笔记
最近在做一个javawebservice项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库。发现了google的gson,因为之前对于protocolbuf有一些了解,带着一些好奇心,我开始使用了gson。经过比较,gson和其他现有javajson类库最大的不同时gson需要序列化得实体类不需要使
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这