Gson gson = new Gson(); // Or use new GsonBuilder().create();
MyType target = new MyType();
String json = gson.toJson(target); // serializes target to Json
MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {对于复杂的集合类型中使用了泛型来限制如 List<Object>, 在Gson里面通过TypeToken类 , 更为通用的方法来有效的解决泛型的问题 。
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
public class TypeToken<T> {
final Class<? super T> rawType;
final Type type;
final int hashCode;
@SuppressWarnings("unchecked")注意: TypeToken<T>类的构造方法是Protected的,使用者必须通过继承的方式,或者匿名类的方式来生成一个TypeToken对象。比如:
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
TypeToken<List<String>> list = new TypeToken<List<String>>() {};//注意:T不能使用带有通配符的参数如Class<?>,或
List<? extends CharSequence>
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
3.1 多个类的嵌套的例子
GSON
可以很容易地序列化和反序列化静态嵌套类。
但是GSON
不能自动反序列化的纯内部类,因为它们的无参构造函数需要引用的对象在反序列化时是无法使用的.
你可以通过使用静态内部类或给它提供一个定制的InstanceCreator
来解决这个问题。下面是一个例子:
//NOTE: 这个class B 在默认情况下不会被`GSON`序列化
public class A {
public String a;
class B {
public String b;
publicB() { // No args constructor for B
}
}
}
}
GSON
不能反序列化{"b":"abc"}
,因为class B
是一个内部类,如果你这么定义B: static class B
, GSON
是能反序列化这段字符串的, 另外一个办法就是自定义个实例构建方法,下面是一个例子
//NOTE: 这样可行,但是不推荐
public class InstanceCreatorForB implements InstanceCreator<A.B> {
privatefinal A a;
public InstanceCreatorForB(A a){
this.a= a;
}
public A.BcreateInstance(Type type){
return a.newB();
}
}
3.2 集合的例子
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]
// (反序列化Deserialization)
Type collectionType =new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);//ints,ints2是一样的
集合限制
- 能够序列化任何任意类型的集合,但是不能让它反序列化,因为使用者没有办法给指示数据类型
- 反序列化的时候,集合一定得是一个特定泛型的集合
3.3 泛型的序列化和反序列化
当你调用toJson(obj)
的时候,GSON
会执行obj.getClass()
来获取序列化的字段的信息,同样的,你可以在fromJson(json, MyClass.class)
方法中使用典型对象.如果对象是一个非泛型对象,这样也能正常工作.但是, 如果对象是一个泛型对象,Java
的类型擦除会让这个对象丢失泛型类型信息.
可以通过使用TypeToken类指定正确的参数化类型的泛型类型来解决这个问题。原理就是上面2.2 Gson解析部分。
3.4 任意对象集合的序列化和反序列化
有时你会处理一些混合类型的JSON
,比如
['hello',5,{
name:'GREETINGS',source:'guest'}]
static class Event{
private String name;
private String source;
privateEvent(String name, String source){
this.name= name;
this.source= source;
}
@Override
public String toString(){
return String.format("(name=%s, source=%s)", name, source);
}
}
public static void main(String[] args){
Gson gson =new Gson();
Collection collection =new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS","guest"));
String json = gson.toJson(collection);
System.out.println("Using Gson.toJson() on a raw collection: "+ json);
JsonParser parser =new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1),int.class);
Event event = gson.fromJson(array.get(2), Event.class);
System.out.printf("Using Gson.fromJson() to get: %s, %d, %s", message, number, event.toString());
}
使用GSON
序列化这个集合只需要调用toJson(collection)
,而且不用设置其他任何东西.但是你要是通过fromJson(json, Collection.class)
反序列化这个集合的话是不可行的,因为GSON
,没办法匹配集合类型,所以GSON
需要你提供这个集合序列化的类型.有三个选则:
- 使用
GSON
的解析器API
(底层流解析器或DOM解析器JsonParser
)来解析数据元素,然后在每一个元素上使用Gson.fromJson()
.这是首选的方法。 - 给
Collection.class
注册类型适配器,让每一个元素都对应自己的对象.缺点是会搞乱
GSON`中其他的集合的反序列化. - 通过注册一个
MyCollectionMemberType
使用fromJson
和Collection<MyCollectionMemberType>
,缺点就是只有数组是顶级元素才是可行的
3.5 从序列化和反序列化中剔除字段
GSON支持剔除顶层类,字段和字段类型,下面是一种排除字段或者类的可插拔的机制,如果这些机制没有满足你的需要.你可以自定义序列化和反序列化的解释器.
默认的情况下,如果一个对象被声明为transient
,static
,那么它就会被剔除. 如果你要包含这些字段,可以用如下代码:
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC)
.create();
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
.create();
自定义的剔除策略
如果这些默认的策略都不能满足你的需求,你还可以自定自己的策略,更多可见ExclusionStrategy
下面是一个使用@Foo
的例子
@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;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return (clazz == typeToSkip);
}
@Override
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);
}
======== OUTPUT ========
{ "longField":1234}3.6 自定义序列化和反序列化
有时默认的内置序列化或反序列化的描述,并不是你想要的,比如做时间之类的处理的时候这种问题经常出现,
Gson
允许你自定义序列化工具:
- Json Serialiers: 需要定义自定义序列化对象
- Json Deserializers: 需要定义自定义反序列化的类型
- Instance Creators: 无参构造方法和反序列化解析器都不是必须的
- 紧凑漂亮的JSON输出
- NULL对象的支持
- 版本支持
- 字段命名支持