Gson完全解析

本文详细介绍了Gson库的使用方法,包括如何将Java对象转换为JSON字符串及反之的操作。提供了序列化与反序列化的示例代码,并解释了Gson配置选项如字段过滤、日期格式化等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章部分实例来自Gson官方用户指导和API,如果有不对的地方,还请各位读者指出。
1.作用:序列化的时候,实现Java对象到Json字符串和Json字符串到Java对象的转变。
2.创建Gson的两种方式
new Gson()创建的实例采用默认的配置,如果需要自己配置,则使用GsonBuilder

Gson gson1 = new Gson();
//or 官方API上的示例代码
Gson gson2 = new GsonBuilder()
     //不包括实体值没有@Expose注解的属性,下面会详细介绍注解
     .excludeFieldsWithoutExposeAnnotation()
     .registerTypeAdapter(Id.class, new IdTypeAdapter())
     .enableComplexMapKeySerialization()
     //配置Gson序列化空字段
     .serializeNulls()
     .setDateFormat(DateFormat.LONG)
     //序列化后字段首字母大写(使用@SerializedName无效)
     .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
     //对Json输出更好的格式化
     .setPrettyPrinting()
     //配置Gson启用版本支持
     .setVersion(1.0)
     .create();

下面一句句进行解释,其余的部分请读者自行阅读官方API

.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()

这两句往往一起,设置了TypeAdapter就可以传进去复杂的属性作为map的key,比如Point {“(5,6):”a”},但是没有设置的话,就会被序列化为一个Json数组嵌套数组

setDateFormat(DateFormat.LONG)

这里可以穿进去两个参数,dateStyle timeStyle
DateFormat.LONG表示yyyy年M月dd日 可以自行设定为”yyyy-MM-dd HH:mm:ss.SSS’Z’”
3.详解序列化和反序列化(采用官方guide的例子)
①序列化 核心代码:gson.toJson(obj)

  • 基本数据类型
Gson gson = new Gson();
gson.toJson(1);            // ==> 1
gson.toJson("abcd");       // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };      // ==> [1]
gson.toJson(values);
  • 对象
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    //无参构造函数
  }
}

// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  

// ==> json is {"value1":1,"value2":"abc"}
  • 数组
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};

// Serialization
gson.toJson(ints);     // ==> [1,2,3,4,5]
gson.toJson(strings);  // ==> ["abc", "def", "ghi"]
  • 集合
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);

// Serialization
String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]

②反序列化 核心代码:gson.fromJson(JsonString,Class of type)

  • 基本数据类型
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String anotherStr = gson.fromJson("[\"abc\"]", String.class);
  • 对象
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    //无参构造函数
  }
}

(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);  
//==> obj2 is just like obj
  • 数组
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};

// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class); 
// ==> ints2 will be same as ints
  • 集合
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);

// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints

4.特点
①.序列化时,空字段跳过输出;反序列化时,Json里面缺少的字段对象里面设置为null
②.反序列化静态内部类的时候会出现问题,反序列化是Json->对象,在反序列内部类的时候,由于内部类默认持有外部类的引用,但是此时外部类还不存在。解决方法:A.设置为静态内部类 B.提供一个传统的InstanceCreator(虽然可行,但是不被推荐)
下面这段代码应设置B为静态的

public class A { 
  public String a; 

  class B { 

    public String b; 

    public B() {
      //B的无参构造函数
    }
  } 
}

③.能序列化Conllection,不能反序列化它,由于没有指定生成对象的类型
④泛型,反序列化的时候,不能得到泛型的类型,只能得到简单的类型,这时使用TypeToken可以获得完全参数类型,这就是为什么要使用TypeToken的原因

class Foo<T> {
  T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // May not serialize foo.value correctly

gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);

gson.fromJson(json, fooType);

4.注解

  • @Expose 在使用new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()创建Gson对象的时候(直接new Gson()的时候没有这种情况),只有@Expose的对象才会被序列化,serialize和deserialize两个值默认为true,如果为false,解释如下
//不会被序列化
@Expose(serialize = false) private String name;
//不会被反序列化
@Expose(deserialize = false)private String id;
  • @SerialzedName 定义属性序列化后的名称
@Expose
@SerialzedName
private String name;
  • transient 不序列化某个属性
private transient String name;
  • 实例
    Java对象:
public class Item {

    @Expose @SerializedName("item_id") private int itemId;
    @Expose(serialize = false) @SerializedName("item_name") private String itemName;
    @SerializedName("nick_name_list") private List<String> nickNameList;

    public Item(int itemId, String itemName) {
        this.itemId = itemId;
        this.itemName = itemName;
    }

    public int getItemId() {
        return itemId;
    }

    public void setItemId(int itemId) {
        this.itemId = itemId;
    }

    public List<String> getNickNameList() {
        return nickNameList;
    }

    public void setNickNameList(List<String> nickNameList) {
        this.nickNameList = nickNameList;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    @Override public String toString() {
        return "Item{" +
                "itemId=" + itemId +
                ", itemName='" + itemName + '\'' +
                ", nickNameList=" + nickNameList +
                '}';
    }

}

下面对上面的代码进行说明(都是通过GsonBuilder来创建Gson对象):
1.所有属性都用@SerializedName把序列化之后的对象名字重新进行了确定
2.itemId 可以同时被序列化和反序列化
itemName 不被序列化,仍然可以被反序列化
nickNameList 不能被序列化和反序列化

@Expose @SerializedName("item_id") private int itemId;
@Expose(serialize = false) @SerializedName("item_name") private String itemName;
@SerializedName("nick_name_list") private List<String> nickNameList;

MainActivity里面的测试代码:

//序列化过程
//创建item1对象
Item item1 = new Item(12,"skylineTan");
List<String> nickNameList = new ArrayList<>();
nickNameList.add("tzy");
nickNameList.add("skyline");
item1.setNickNameList(nickNameList);

//两种方式创建Gson对象
Gson gson = new Gson();
Log.d(TAG_MAIN_ACTIVITY,gson.toJson(item1));
Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Log.d(TAG_MAIN_ACTIVITY,gsonBuilder.toJson(item1));

//反序列化过程
//得到Json字符串
String s = gson.toJson(item1);
//得到item2
Item item2 = gson.fromJson(s,Item.class);
Log.d(TAG_MAIN_ACTIVITY,item2.toString());
//得到item3
Item item3 = gsonBuilder.fromJson(s,Item.class);
Log.d(TAG_MAIN_ACTIVITY,item3.toString());

输出结果:

//序列化过程
D/MainActivity: {"item_id":12,"item_name":"skylineTan","nick_name_list":["tzy","skyline"]}
D/MainActivity: {"item_id":12}
//反序列化过程
D/MainActivity: Item{itemId=12, itemName='skylineTan', nickNameList=[tzy, skyline]}
//itemName仍然可以被反序列化,nickNameList序列化和反序列化都不行
D/MainActivity: Item{itemId=12, itemName='skylineTan', nickNameList=null}

参考文章:
Gson User Guide
Gson API

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值