Json轉換神器之Google Gson的使用

這幾天,由於項目的須要,接觸了Google的Gson庫,發現這個東西很好用,遂記下簡單的筆記,供之後參考。至於Gson是幹什麼的,有什麼優勢,請各位同窗自行百度。html

1. 下載Gson

拷貝到項目的lib文件夾中,並將其加入到buildPath中。使用maven的同窗,直接在pom中加入如下依賴便可:java

<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));
  }
}

輸出結果:json

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

4. 序列化部分字段

以上只是Gson的簡單實用,若是咱們須要將bool類型的屬性setName在轉換成json的時候不轉換,怎麼實現呢? maven

4.1 使用Java的transient關鍵字過濾

讓字段不序列化的最簡單的方式就是使用Java的關鍵字transient:ide

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

第3步測試類不變,則會有如下輸出:svn

{"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個屬性。然而,若是你使用ui

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

來建立Gson對象,Gson 的 toJson() 和 fromJson() 方法將會排除掉 setName 段,這是由於 setName 字段沒有被註解 @Expose 所標記。 這個 Gson 對象一樣會排除 age 字段,由於註解@Expose的屬性 serialize 被設置成了 false。相似的,Gson也會在反序列化時排除掉 age 字段,由於 deserialize被設置成了 false。this

第3步測試類只改變Gson對象的建立過程,則會有如下輸出:google

{"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

相關文章
相關標籤/搜索