在下面这个例子中,POJO(Data类)是一个范型类,在Tests中,指定范型类为PieceData,POJO初始化完成后,通过
String str = new Gson().toJson(data);
得到范型化的POJO序列化得到的JSON串,然后将这个JSON串反序列化为POJO
import com.google.gson.Gson; import java.util.ArrayList; import java.util.List; class PieceData { private String name; private int weight; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } } class Data<T> { List<T> pieces; public List<T> getPieces() { return pieces; } public void setPieces(List<T> pieces) { this.pieces = pieces; } } public class Tests { public static void main(String[] args) { PieceData data1 = new PieceData(); data1.setName("Cat"); data1.setWeight(6); PieceData data2 = new PieceData(); data2.setName("Dog"); data2.setWeight(36); List<PieceData> pieces = new ArrayList<PieceData>(); pieces.add(data1); pieces.add(data2); Data<PieceData> data = new Data<PieceData>(); data.setPieces(pieces); String str = new Gson().toJson(data); System.out.println(str); Data<PieceData> result = new Gson().fromJson(str, Data.class); for (int i = 0; i < result.getPieces().size(); i++) { Object o = result.getPieces().get(i); System.out.println(o.getClass() + "\t" + o); // System.out.println(piece.getName() + "\t" + piece.getWeight()); } } }
针对上面的代码,有如下分析:
1. POJO序列化的JSON串是{"pieces":[{"name":"Cat","weight":6},{"name":"Dog","weight":36}]}
2. Data<PieceData> result = new Gson().fromJson(str, Data.class);为什么可以编译通过,直观的感觉是因为参数是Data.class,因此返回值只能是Data result = new Gson().fromJson(str, Data.class):通过察看Gson的fromJson方法 public <T> T fromJson(String json, Class<T> classOfT),看不出来上面的代码为什么可以编译通过
3. 上面的代码输出是
{"pieces":[{"name":"Cat","weight":6},{"name":"Dog","weight":36}]}
class com.google.gson.internal.LinkedTreeMap {name=Cat, weight=6.0}
class com.google.gson.internal.LinkedTreeMap {name=Dog, weight=36.0}
为什么result.getPieces()返回的List,其中的数据类型为TreeMap,明明是PieceData的,原因我猜想,虽然代码中,result类型由于是Data<PieceData>,即result.getPieces()应该是PieceData的集合,可实际运行时,范型有个特性称为Generics Erasure,也就是说实际运行中result.getPieces()未必是PieceData的集合,在这里是TreeMap的集合,TreeMap保存的是PieceData数据的key-value对。
4.可否把
Data<PieceData> result = new Gson().fromJson(str, Data.class);
改为
Data<PieceData> result = new Gson().fromJson(str, Data<PieceData>.class);
不可以!编译不通过,为什么Data<PieceData>编译出错
5. 使用Type包装Data<PieceData>,代码如下
package generic; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; class PieceData { private String name; private int weight; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } } class Data<T> { List<T> pieces; public List<T> getPieces() { return pieces; } public void setPieces(List<T> pieces) { this.pieces = pieces; } } public class Tests { public static void main(String[] args) { PieceData data1 = new PieceData(); data1.setName("Cat"); data1.setWeight(6); PieceData data2 = new PieceData(); data2.setName("Dog"); data2.setWeight(36); List<PieceData> pieces = new ArrayList<PieceData>(); pieces.add(data1); pieces.add(data2); Data<PieceData> data = new Data<PieceData>(); data.setPieces(pieces); String str = new Gson().toJson(data); System.out.println(str); Type type = new TypeToken<Data<PieceData>>() { }.getType(); Data<PieceData> result = new Gson().fromJson(str, type); for (int i = 0; i < result.getPieces().size(); i++) { Object o = result.getPieces().get(i); System.out.println(o.getClass() + "\t" + o); PieceData p = result.getPieces().get(i); System.out.println(p.getName() + "\t" + p.getWeight()); } } }
此时结果符合预期
{"pieces":[{"name":"Cat","weight":6},{"name":"Dog","weight":36}]}
class generic.PieceData generic.PieceData@674a93a6
Cat 6
class generic.PieceData generic.PieceData@5123ac44
Dog 36
总结
1.当要反序列化的POJO是范型POJO时,如例子中的Data,那么必须使用TypeToken对范型进行包装,即调用public <T> T fromJson(String json, Type typeOfT)
2.如果POJO本身不是范型类,但是POJO中包含范型集合时,可以不使用TypeToken进行包装,即调用 public <T> T fromJson(String json, Class<T> classOfT)即可完成反序列化,参见http://bit1129.iteye.com/blog/2101301
3.public <T> T fromJson(String json, Type typeOfT)和public <T> T fromJson(String json, Class<T> classOfT)的javadoc明确说明了它们的应用场景
public <T> T fromJson(String json, Class<T> classOfT)
/* public <T> T fromJson(String json, Class<T> classOfT) deserializes the specified Json into an object of the specified class. It is not
* suitable to use if the specified class is a generic type since it will not have the generictype information because of the Type Erasure feature of Java. Therefore, this method should not
* be used if the desired type is a generic type. Note that this method works fine if the any of the fields of the specified object are generics, just the object itself should not be a
* generic type. For the cases when the object is of generic type, invoke {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
* a String, use {@link #fromJson(Reader, Class)} instead.
*/
public <T> T fromJson(String json, Type typeOfT)
/** * This method deserializes the specified Json into an object of the specified type. This method * is useful if the specified object is a generic type. For non-generic objects, use * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of * a String, use {@link #fromJson(Reader, Type)} instead. * * @param <T> the type of the desired object * @param json the string from which the object is to be deserialized * @param typeOfT The specific genericized type of src. You can obtain this type by using the * {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for * {@code Collection<Foo>}, you should use: * <pre> * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType(); * </pre> * @return an object of type T from the string * @throws JsonParseException if json is not a valid representation for an object of type typeOfT * @throws JsonSyntaxException if json is not a valid representation for an object of type */
相关推荐
Gson 中解决 json 反序列化时相同属性对应不同类型的值的问题(代码),对应文章链接:https://blog.csdn.net/ZiFung_Yip/article/details/89143255
实现了通过gson对enum的自定义转化过程,不需要预先定义enmu,并且不需要修改gson源码,在框架顶层处理基本可以达到对enum的抽象管理。
Gson解析之自定义序列化和反序列化的代码例子,但后端对同一个字段给的数据类型与文档不一致时的处理
fastJosn Gson Jackson 序列化和反序列化所需要的jar,已经全部验证过,请放心使用咯
fastjson、gson、jackson序列化和反序列化所用json文件
格森Gson是一个Java库,可用于将Java对象转换为其JSON表示形式。 它还可以用于将JSON字符串转换为等效的Java对象。 Gson可以处理任意Java对象,包括您没有源代码的现有对象。 有一些开源项目可以将Java对象转换为...
gson序列化,反序列化工具包,用来做工具报表使用,
1.2 JavaBean序列化/反序列化 1.2.1 步骤说明 普通JavaBean 嵌套JavaBean 1.3 数组和List的序列化/反序列化 1.3.1 数组的序列化/反序列化 1.3.2 List集合的序列化/反序列化 1.4 Set和Map的序列化/反序列化 1.4.1 Set...
集成多枚举类型统一序列化/反序列化处理,再也不用创建多个Adapter了 http://blog.csdn.net/atm008/article/details/51733849
gson-2.0.1.jar-Json解析工具,序列化反序列化,实体类互转Json,免费jar包
【Android Protobuf 序列化】Protobuf 性能测试 ( fastjson 序列化与反序列化 | gson 序列化与反序列化 | 三种序列化与反序列化性能对比 ) https://hanshuliang.blog.csdn.net/article/details/116199062 【Android ...
主要讲述Json序列化与反序列化,主要使用Gson、FastJson、Jackson实现
Android基于Gson序列化和反序列化,用于存储对象到xml和从xml中解析对象
Gson jackson fastjson LoganSquare 使用demo Gson jackson fastjson LoganSquare 使用demo
GSON是Google开发并开源的一个Java的JSON转换库,这里我们将来讲解GSON实现Java对象的JSON序列化与反序列化的实例教程,需要的朋友可以参考下
使用Jackson进行json序列化的小例子。
Gson反序列化原理 原理简述 gson反序列化主要分为两个过程: 根据TypeToken创建出对象 根据json字符串解析数据,对对象属性赋值 对象的创建 ConstructorConstructor.get 先尝试获取无参构造函数 失败则尝试...
protostuff fastjson gson 高性能序列化jar包
Gson和HttpComponent 测试Java Gson和HttpComponent库,序列化arrayList并使用REST服务
可以将一个JSON字符串转成一个Java对象(反序列化),或者反过来(序列化)。 GSON地址:google/gson (github.com) Android引入GSON: implementation ‘com.google.code.gson:gson:2.9.0’ Gson 是 Google 提供的...