GSON使用介绍

2018/09/25 swaiter

Gson介绍 Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。而JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。 下载地址:https://mvnrepository.com/artifact/com.google.code.gson/gson 对象转JSON 单独转一个对象

Article item;
Gson gson = new Gson();
String result = gson.toJson(item);

输出结果:

{"id":1,"uuid":"868621d3-d55d-486e-bd7e-1f2df5ec4746","title":"Update Test Title","categories":"Update Test Categories","tags":"Update Test Tags","createTime":"May 23, 2017 11:38:38 PM","updateTime":"May 24, 2017 9:46:46 PM","enable":true}

转一组对象

List<Article> items;
Gson gson = new Gson();
String result = gson.toJson(items);

输出结果:

{"[{"id":1,"uuid":"868621d3-d55d-486e-bd7e-1f2df5ec4746","title":"Update Test Title","categories":"Update Test Categories","tags":"Update Test Tags","createTime":"May 23, 2017 11:38:38 PM","updateTime":"May 24, 2017 9:46:46 PM","enable":true},{"id":2,"uuid":"e58d3d06-8a40-4d64-9329-7a4be87ba1dc","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"May 23, 2017 11:44:41 AM","updateTime":"May 23, 2017 11:44:41 AM","enable":true},{"id":3,"uuid":"bb662958-398d-4d53-b7c6-9738832b0781","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"May 23, 2017 8:42:01 PM","updateTime":"May 23, 2017 8:42:01 PM","enable":true}]

设置日期时间格式

List<Article> items;
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss");
Gson gson = gsonBuilder.create();
String result = gson.toJson(items);

输出结果:

[{"id":1,"uuid":"868621d3-d55d-486e-bd7e-1f2df5ec4746","title":"Update Test Title","categories":"Update Test Categories","tags":"Update Test Tags","createTime":"2017-05-23 23-38-38","updateTime":"2017-05-24 21-46-46","enable":true},{"id":2,"uuid":"e58d3d06-8a40-4d64-9329-7a4be87ba1dc","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"2017-05-23 11-44-41","updateTime":"2017-05-23 11-44-41","enable":true},{"id":3,"uuid":"bb662958-398d-4d53-b7c6-9738832b0781","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"2017-05-23 20-42-01","updateTime":"2017-05-23 20-42-01","enable":true}]

隐藏某些域:

List<Article> items;
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {
    @Override
    public boolean shouldSkipField(FieldAttributes fieldAttributes) {
        String[] skipFields = {"enable"};
        String field = fieldAttributes.getName().toLowerCase();
        for (String skipField : skipFields)
            if (field.equals(skipField))
                return true;
        return false;
    }
    @Override
    public boolean shouldSkipClass(Class<?> aClass) {
        return false;
    }
});
Gson gson = gsonBuilder.create();
String result = gson.toJson(items);

输出结果:

[{"id":1,"uuid":"868621d3-d55d-486e-bd7e-1f2df5ec4746","title":"Update Test Title","categories":"Update Test Categories","tags":"Update Test Tags","createTime":"2017-05-23 23:38:38","updateTime":"2017-05-24 21:46:46"},{"id":2,"uuid":"e58d3d06-8a40-4d64-9329-7a4be87ba1dc","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"2017-05-23 11:44:41","updateTime":"2017-05-23 11:44:41"},{"id":3,"uuid":"bb662958-398d-4d53-b7c6-9738832b0781","title":"Test Title","categories":"Test Categories","tags":"Test Tags","createTime":"2017-05-23 20:42:01","updateTime":"2017-05-23 20:42:01"}]

JSON转对象 首先建立JSON对应的对象

class JsonHolder {
    public boolean success;
    public String uuid;
    public String message;
}

转单个对象 编写测试代码

@Test
public void testJsonObeject() {
    String uuid = "4b10e722-0699-4590-90d3-0e7e12358518";
    String json = "{\"success\":true, \"uuid\":\"" + uuid + "\"}";
    json = "{\"success\":false, \"message\":\"can't create new file!\"}";
    JsonHolder item = new Gson().fromJson(json, JsonHolder.class);
    System.out.println(item.success);
    System.out.println(item.uuid);
    System.out.println(item.message);
}

输出结果

false
null
can't create new file!

转一组对象 编写测试代码

@Test
public void testJsonObeject() {
    String uuid = "4b10e722-0699-4590-90d3-0e7e12358518";
    String json = "{\"success\":true, \"uuid\":\"" + uuid + "\"}";
    String longJson = "[" + json + ","  + json + "," + json + "]";
    JsonHolder[] items = new Gson().fromJson(longJson, JsonHolder[].class);
    for (JsonHolder item : items) {
        System.out.println(item.success);
        System.out.println(item.uuid);
        System.out.println(item.message);
    }
}

转复杂对象 先给出一个比较复杂的JSON

{
  "error": 0,
  "status": "success",
  "date": "2014-05-10",
  "results": [
    {
      "currentCity": "南京",
      "weather_data": [
        {
          "date": "周六(今天, 实时:19℃)",
          "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/dayu.png",
          "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/dayu.png",
          "weather": "大雨",
          "wind": "东南风5-6级",
          "temperature": "18℃"
        },
        {
          "date": "周日",
          "dayPictureUrl": "http://api.map.baidu.com/images/weather/day/zhenyu.png",
          "nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
          "weather": "阵雨转多云",
          "wind": "西北风4-5级",
          "temperature": "21 ~ 14℃"
        }
      ]
    }
  ]
}

构造接收这个JSON的对象:

class JsonHolder {
    public int error;
    public String status;
    public String date;
    public A[] results;
    class A {
        public String currentCity;
        public B[] weather_data;
        class B {
            public String date;
            public String dayPictureUrl;
            public String nightPictureUrl;
            public String weather;
            public String wind;
            public String temperature;
        }
    }
}

编写测试代码

@Test
public void testJsonObeject() throws IOException {
    String json = "";
    BufferedReader br = new BufferedReader(new FileReader("/home/alan/Documents/WorkSpace/Intellij_IDEA_workspace/MyBlog/test/json.txt"));
    String line = "";
    while ((line = br.readLine()) != null) {
        json += line;
    }
    br.close();
    JsonHolder jsonHolder = new Gson().fromJson(json, JsonHolder.class);
    System.out.println(jsonHolder.status);
    System.out.println(jsonHolder.results[0].currentCity);
    System.out.println(jsonHolder.results[0].weather_data[1].weather);
    System.out.println(jsonHolder.results[0].weather_data[1].temperature);
}

结果:

success
南京
阵雨转多云
21 ~ 14

1、多泛型变量定义及字母规范

(1)、多泛型变量定义 上在我们只定义了一个泛型变量T,那如果我们需要传进去多个泛型要怎么办呢?

只需要在类似下面这样就可以了:

class MorePoint<T,U>{  
}  

(2)、字母规范 在定义泛型类时,我们已经提到用于指定泛型的变量是一个大写字母: 当然不是的!!!!任意一个大写字母都可以。他们的意义是完全相同的,但为了提高可读性,大家还是用有意义的字母比较好,一般来讲,在不同的情境下使用的字母意义如下:

  • E — Element,常用在java Collection里,如:List,Iterator,Set
  • K,V — Key,Value,代表Map的键值对
  • N — Number,数字
  • T — Type,类型,如String,Integer等等

### 2、泛型函数定义及使用

怎么单独在一个函数里使用泛型。比如我们在新建一个普通的类StaticFans,然后在其中定义了两个泛型函数:

public class StaticFans {  
    //静态函数  
    public static  <T> void StaticMethod(T a){  
        Log.d("harvic","StaticMethod: "+a.toString());  
    }  
    //普通函数  
    public  <T> void OtherMethod(T a){  
        Log.d("harvic","OtherMethod: "+a.toString());  
    }  
}  

上面分别是静态泛型函数和常规泛型函数的定义方法,与以往方法的唯一不同点就是在返回值前加上来表示泛型变量。其它没什么区别。 使用方法如下:

//静态方法  
StaticFans.StaticMethod("adfdsa");//使用方法一  
StaticFans.<String>StaticMethod("adfdsa");//使用方法二  
  
//常规方法  
StaticFans staticFans = new StaticFans();  
staticFans.OtherMethod(new Integer(123));//使用方法一  
staticFans.<Integer>OtherMethod(new Integer(123));//使用方法二  

首先,我们看静态泛型函数的使用方法:

StaticFans.StaticMethod("adfdsa");//使用方法一  
StaticFans.<String>StaticMethod("adfdsa");//使用方法二  

从结果中我们可以看到,这两种方法的结果是完全一样的,但他们还有些区别的,区别如下: 方法一,可以像普通方法一样,直接传值,任何值都可以(但必须是派生自Object类的类型,比如String,Integer等),函数会在内部根据传进去的参数来识别当前T的类别。但尽量不要使用这种隐式的传递方式,代码不利于阅读和维护。因为从外观根本看不出来你调用的是一个泛型函数。 方法二,与方法一不同的地方在于,在调用方法前加了一个来指定传给的值,如果加了这个来指定参数的值的话,那StaticMethod()函数里所有用到的T类型也就是强制指定了是String类型。这是我们建议使用的方式。 同样,常规泛型函数的使用也有这两种方式:

StaticFans staticFans = new StaticFans();  
staticFans.OtherMethod(new Integer(123));//使用方法一  
staticFans.<Integer>OtherMethod(new Integer(123));//使用方法二 

可以看到,与平常一样,先创建类的实例,然后调用泛型函数。 方法一,隐式传递了T的类型,与上面一样,不建议这么做。 方法二,显示将T赋值为Integer类型,这样OtherMethod(T a)传递过来的参数如果不是Integer那么编译器就会报错。

进阶:返回值中存在泛型 上面我们的函数中,返回值都是void,但现实中不可能都是void,有时,我们需要将泛型变量返回,比如下面这个函数:

public static <T> List<T> parseArray(String response,Class<T> object){  
    List<T> modelList = JSON.parseArray(response, object);  
    return modelList;  
}  

函数返回值是List类型。至于传入参数Class object的意义,我们下面会讲。这里也就是想通过这个例子来告诉大家,泛型变量其实跟String,Integer,Double等等的类的使用上没有任何区别,T只是一个符号,可以代表String,Integer,Double……这些类的符号,在泛型函数使用时,直接把T看到String,Integer,Double……中的任一个来写代码就可以了。唯一不同的是,要在函数定义的中在返回值前加上标识泛型;

3、其它用法:Class类传递及泛型数组

(1)、使用Class传递泛型类Class对象 有时,我们会遇到一个情况,比如,我们在使用JSON解析字符串的时候,代码一般是这样的

public static List<SuccessModel> parseArray(String response){  
    List<SuccessModel> modelList = JSON.parseArray(response, SuccessModel.class);  
    return modelList;  
} 

其中SuccessModel是自定义的解析类,代码如下,其实大家不用管SuccessModel的定义,只考虑上面的那段代码就行了。写出来SuccessModel的代码,只是不想大家感到迷惑,其实,这里只是fastJson的基本用法而已。 这段代码的意义就是根据SuccessModel解析出List的数组。

public class SuccessModel {  
    private boolean success;  
      
    public boolean isSuccess() {  
        return success;  
    }  
  
    public void setSuccess(boolean success) {  
        this.success = success;  
    }  
}   

首先,我们应该把SuccessModel单独抽出来做为泛型变量,但parseArray()中用到的SuccessModel.class要怎么弄呢? 先来看代码:

public static <T> List<T> parseArray(String response,Class<T> object){  
    List<T> modelList = JSON.parseArray(response, object);  
    return modelList;  
}  

下面是我自己实际使用泛型的几个实例。 希望看完上面的文章之后,再看实际使用的例子,可以更好的理解和使用和实际使用。 关于泛型类的使用实例

import lombok.Data;
 
@Data
public class MultiObject<T> {
 
	/**
     * 成功状态
     */
    private boolean success;
 
    /**
     * 异常
     */
    private Exception ex;
 
    /**
     * 数据
     */
    private T obj;
	
	public MultiObject() {
	}
 
	/**
	 * 注意:当传入的泛型是Boolean时,就和第三个构造函数冲突了。
	 */
	public MultiObject(boolean success) {
		this.success = success;
	}
	
	public MultiObject(Exception ex) {
		this.success = false;
		this.ex = ex;
	}
	
	public MultiObject(T value) {
		this.success = true;
		this.obj = value;
	}
}

简单解释下这个model。 在实际业务代码里面,可能有很多种操作,然后我们关心这个操作的执行结果,主要有几点。 1,成功与否。对应属性success。 2,异常信息。对应属性ex。若是操作正常执行,则就不在意这个属性的值。 3,我们操作的最终目的对象。对应属性obj。 依赖的包 ```apple js org.projectlombok lombok 1.18.4 provided

关于泛型方法的使用实例
这个地方就有2个,但是上面文章也都讲到啦。
1,一个是泛型表示某一个类型的参数。为的传递某一类的参数对象
2,另一个则是传递的不是参数,而是代表Class,某一个类。

恰巧我都使用过,就正好记录一下实际使用实例。
```java
  /**
     * 将Json字符串信息转换成对应的Java对象
     *
     * @param json json字符串对象
     * @param c    对应的类型
     */
    public static <T> T parseJsonToObj(String json, Class<T> c) {
        try {
            JSONObject jsonObject = JSONObject.parseObject(json);
            return JSON.toJavaObject(jsonObject, c);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
        return null;
    }

然后是具体调用的地方的代码。

Collector collectorObj = JSONUtils.parseJsonToObj(collector, Collector.class);
Flume flume = JSONUtils.parseJsonToObj(flumeJson, Flume.class);
Probe probe = JSONUtils.parseJsonToObj(probeJson, Probe.class);

可以看到,真的只是因为传入的参数类型不一样,但若你不知道泛型的话,那你就得没遇到一个类型的转换,你就得写一个这么个方法。

 /**
     * @param dest   目的集合
     * @param source 源集合
     * @param <T>    集合参数的类型
     */
    private static <T> void listAddAllAvoidNPE(List<T> dest, List<T> source) {
        if (source == null) {
            return;
        }
        dest.addAll(source);
    }
 
    private static <T> void listAddAvoidNull(List<T> dest, T source) {
        if (source == null) {
            return;
        }
        dest.add(source);
    }

这个就是传入的参数为某一类的参数,主要是要使用参数对象,而不是上面的那个使用的参数的类Class 我这方法提出来,主要是因为,直接使用list类的addAll()方法,如果添加的是null,那么就会抛异常。但是总不能我在所有使用的地方,都判断一下我要添加的参数是不是null,然后再调用list的addAll()方法吧。那样的话,这样的判断代码会啰嗦的海了去了。所以,就这么提出来了。 这个时候,这个T,使用起来就像使用我们常用的一般对象一样,我这的参数是个List类型,当然也可是其他类型的,姿势都一样。

然后是具体调用的地方的代码

List<ProbeObject> list = Lists.newArrayList();
	listAddAllAvoidNPE(list, decoder.getProperties());

这个方法的第二个参数的返回值可能是null,所以,直接调用addAll(),就会抛空指针异常。所以,就如上,那么一提取。就好多啦。

Search

    Table of Contents