Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> gson用戶指南(下)

gson用戶指南(下)

編輯:關於Android編程

上篇文章gson用戶指南(上)翻譯到了10、序列化和反序列化有任意類型對象的collection

我們繼續

11、內置的序列化器和反序列化器

Gson內置的常用的默認序列化器和反序列化器的類可能不合適。比如
java.net.URL to match it with strings like "https://github.com/google/gson/"
java.net.URI to match it with strings like "/google/gson/"
你可以從源碼中找到一些常用的類。例如JodaTime點擊打開鏈接

12、自定義序列化和反序列化

有時候默認表示不是你想要的。通常情況下在處理庫類(DateTime等)會遇到這種情況。Gson允許注冊你的自定義的序列化器和反序列化器。主要需要定義兩個部分: Json序列化器:自定義對象的序列化 Json反序列化器:為一個類型自定義反序列化 實例化構造器:需要一個無參數構造方法,或者注冊一個反序列化器
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerTypeAdapter(MyType.class, new MyDeserializer());
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
registerTypeAdapter調用檢查類型適配器實現一個以上的接口,注冊它。

13、寫一個序列化器

JodaTime DateTime 類的示例
private class DateTimeSerializer implements JsonSerializer {
  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(src.toString());
  }
}
當它運行到一個DateTime對象序列化時。Gson會調用serialize()。

14、寫一個反序列化器

JodaTime DateTime 類的示例
private class DateTimeDeserializer implements JsonDeserializer {
  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    return new DateTime(json.getAsJsonPrimitive().getAsString());
  }
}
當需要一個JSON字符串反序列化
為DateTime對象時,Gson會調用deserialize 方法。

序列化與反序列化的細節

通常你想為所有泛型類型對應的原始類型注冊一個handler
例如,假如你有一個Id類來表示id
Id類型有相同的序列化泛型類型,本質上是輸出Id的值
反序列化相似但是不同,需要調用new Id(Class, String) 來創建實例 Gson支持注冊一個handler。你也可以為一個特定的泛型類型(比如Id < RequiresSpecialHandling >需要特殊處理)注冊一個特殊的handler。toJson的類型參數()和fromJson()包含泛型類型信息來幫助你編寫一個為所有泛型類型對應相同原始類型的handler。

15、編寫實例創建者

當反序列化一個對象的時候,Gson需要創建類的默認對象,一個正常序列化和反序列化的類需要有無參構造方法。
無論是public的還是private的都可以
通常,在處理一個沒有無參構造方法的庫中的類的時候才需要實例創建器。 示例
private class MoneyInstanceCreator implements InstanceCreator {
  public Money createInstance(Type type) {
    return new Money("1000000", CurrencyCode.USD);
  }
}
Type 可以是相應的泛型 調用構造函數需要特定的泛型類型信息

16、InstanceCreator參數化類型

有時你試圖實例化的類型是參數化的類型。一般來說,這不會是一個問題,因為有實際的原始類型的實例。這是一個例子:
class MyList extends ArrayList {
}

class MyListInstanceCreator implements InstanceCreator> {
    @SuppressWarnings("unchecked")
  public MyList createInstance(Type type) {
    // No need to use a parameterized list since the actual instance will have the raw type anyway.
    return new MyList();
  }
}
然而,有時你需要根據實際參數化類型創建實例。這種情況下,可以使用傳遞到createInstance方法的類型參數,例如
public class Id {
  private final Class classOfId;
  private final long value;
  public Id(Class classOfId, long value) {
    this.classOfId = classOfId;
    this.value = value;
  }
}

class IdInstanceCreator implements InstanceCreator> {
  public Id createInstance(Type type) {
    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
    Type idType = typeParameters[0]; // Id has only one parameterized type T
    return Id.get((Class)idType, 0L);
  }
}
在上面的示例中,如果沒有傳遞參數化類型的真實類型,不能創建Id類的實例。我們通過方法參數傳遞類型type來解決這個問題。在本例中Java對象是類型參數化的類型表示的Id < Foo >應該綁定到實例Id < Foo >。由於Id類只有一個參數化的類型參數T,我們使用getActualTypeArgument()返回的第0個元素類型的數組將持有Foo.class

17、緊湊輸出和格式化輸出Json對比

默認json輸出是緊湊格式,這意味著json結構中沒有空格。名稱和值,對象字段和對象數組中的JSON輸出不會有空白字段。 null字段將在輸出中被忽略(注意:null值仍將包含在集合/數組對象中)。 如果要使用格式化輸出,需要在用GsonBuilder構建Gson時配置。JsonFormatter 不是公有的,外部不能直接調用。到目前為止,內部只有JsonPrintFormatter 一個格式化輸出,默認一行80個字符,2個字符縮進,4個字符的右間距 示例
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson.toJson(someObject);

18、對Null對象的支持

Gson默認情況下 null對象字段會被忽略。這樣允許一個更緊湊的輸出格式;然而客戶端必須為這些字段定義一個默認值將JSON格式轉換回Java形式。 這是使Gson支持null對象輸出的方法
Gson gson = new GsonBuilder().serializeNulls().create();
注意,當使用Gson序列化null對象時,會在JsonElement 結構中增加JsonNull ,這個對象不能用於自定義序列化反序列化 示例
public class Foo {
  private final String s;
  private final int i;

  public Foo() {
    this(null, 5);
  }

  public Foo(String s, int i) {
    this.s = s;
    this.i = i;
  }
}

Gson gson = new GsonBuilder().serializeNulls().create();
Foo foo = new Foo();
String json = gson.toJson(foo);
System.out.println(json);

json = gson.toJson(null);
System.out.println(json);
輸出
{"s":null,"i":5}
null

19、版本支持

同一對象的多個版本可以使用@Since注解。這個注解可用於類、字段和未來的方法中。利用這一特性,可以配置Gson實例忽略當大於一些版本號的任何字段/對象。如果沒有設置版本Gson實例就會進行序列化和反序列化所有字段和類。
public class VersionedClass {
  @Since(1.1) private final String newerField;
  @Since(1.0) private final String newField;
  private final String field;

  public VersionedClass() {
    this.newerField = "newer";
    this.newField = "new";
    this.field = "old";
  }
}

VersionedClass versionedObject = new VersionedClass();
Gson gson = new GsonBuilder().setVersion(1.0).create();
String jsonOutput = gson.toJson(someObject);
System.out.println(jsonOutput);
System.out.println();

gson = new Gson();
jsonOutput = gson.toJson(someObject);
System.out.println(jsonOutput);

輸出
{"newField":"new","field":"old"}

{"newerField":"newer","newField":"new","field":"old"}

20、排除序列化和反序列化字段

Gson支持眾多不包括頂級類、字段和字段類型機制。以下是靈活的機制,允許將字段和類排除在外。如果沒有一個機制滿足您的需求然後你可以使用自定義序列化器和反序列化器。

java關鍵字

默認情況下,如果一個字段標記為瞬態,它將被排除在外。,如果字段標記為靜態,那麼在默認情況下將被排除在外。如果你想包括一些字段你可以這樣
import java.lang.reflect.Modifier;
Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC)
    .create();
可以添加多個常量
Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
    .create();

21、Gson的@Expose注解

這個特性提供了一種方法,可以標記某些字段的對象排除序列化和反序列化為JSON。使用這個注解,必須調用new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()。這樣@Expose注解的類和字段才能被序列化和反序列化。

22、自定義排除策略

如果排除字段和類類型上述機制不適合你,那麼你可以編寫自己的排斥戰略,並把它應用到GSON。詳細信息請參照文檔,文檔地址ExclusionStragegy

示例

 

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Foo {
  // Field tag only annotation
}

public class SampleObjectForTest {
  @Foo private final int annotatedField;
  private final String stringField;
  private final long longField;
  private final Class clazzField;

  public SampleObjectForTest() {
    annotatedField = 5;
    stringField = "someDefaultValue";
    longField = 1234;
  }
}

public class MyExclusionStrategy implements ExclusionStrategy {
  private final Class typeToSkip;

  private MyExclusionStrategy(Class typeToSkip) {
    this.typeToSkip = typeToSkip;
  }

  public boolean shouldSkipClass(Class clazz) {
    return (clazz == typeToSkip);
  }

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

public static void main(String[] args) {
  Gson gson = new GsonBuilder()
      .setExclusionStrategies(new MyExclusionStrategy(String.class))
      .serializeNulls()
      .create();
  SampleObjectForTest src = new SampleObjectForTest();
  String json = gson.toJson(src);
  System.out.println(json);
}

輸出

 

 

{"longField":1234}

 

23、對Json字段命名的支持

Gson支持一些預先定義的字段命名策略轉換標准的Java字段名,例如小寫字母開頭的駝峰式命名,詳細信息可以參考文檔FieldNamingPolicy

它也有一個基於注解的策略,允許客戶端自定義名稱。請注意,基於策略的注解有字段名的驗證,如果一個無效的字段名稱作為注解將增加運行異常。
下面是一個自定義命名策略的例子

 

private class SomeObject {
  @SerializedName("custom_naming") private final String someField;
  private final String someOtherField;

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

SomeObject someObject = new SomeObject("first", "second");
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
String jsonRepresentation = gson.toJson(someObject);
System.out.println(jsonRepresentation);

輸出

 

 

{"custom_naming":"first","SomeOtherField":"second"}

相關地址

 

http://groups.google.com/group/google-gson/browse_thread/thread/cb441a2d717f6892
http://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html

24、共享序列化和反序列化狀態

有時候需要共享序列化反序列化,可以用下面三個方法
(1)通過靜態字段存儲共享狀態
(2)在父類中定義序列化反序列化內部類,並使用父類型的實例字段來存儲共享狀態。
(3)使用ThreadLocal
1,2是線程不安全的,3是線程安全的

25、流的處理

除了Gson的對象模型和數據綁定,可使用GSON讀取和寫入流。也可以流和對象模型的訪問都是用,以獲得最佳的方法。

 

 

七、Gson的設計

見GSON設計文檔,對設計GSON時我們面臨的問題進行了探討。也包括GSON與可用於JSON的轉換其他Java庫的比較。
參考地址https://sites.google.com/site/gson/gson-design-document

八、未來Gson的增強功能

建議的改進的最新列表,或者如果你想建議更新的內容,請參照地址https://github.com/google/gson/issues


終於譯完了,有點繞。

gson是非常不錯的json解析框架。使用上比較簡單,功能強大,效率上也不錯。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved