当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

【Gson四】范型POJO的反序列化

发表于: 2014-08-13   作者:bit1129   来源:转载   浏览:
摘要: 在下面这个例子中,POJO(Data类)是一个范型类,在Tests中,指定范型类为PieceData,POJO初始化完成后,通过 String str = new Gson().toJson(data); 得到范型化的POJO序列化得到的JSON串,然后将这个JSON串反序列化为POJO   import com.google.gson.Gson; import java.

在下面这个例子中,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&lt;Collection&lt;Foo&gt;&gt;(){}.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四】范型POJO的反序列化

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
在详细介绍Gson的序列化和反序列化之前,先通过自己在开发过程中遇到的一个问题以及简单的解决方案
[.net 面向对象程序设计进阶] (12) 序列化(Serialization)(四) 快速掌握JSON的序列化和反序列化 本
本文内容按如下方式组织: 第一部分给出了序列化和反序列化的定义,以及其在通讯协议中所处的位置;
最近公司项目中用到了Json操作,从.NET后台读取数据,通过Json转化在传给“Andiron”端呈现,于是通
原文出处:http://www.ibm.com/developerworks/cn/java/j-lo-serial/ 引言 将 Java 对象序列化为二
windows phone学习也有一段时间了,想要做一个新闻客户端练练手,于是就在网上找看有没有接口之类。
基本概念: 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流
序列化和反序列化我们可能经常会听到,其实通俗一点的解释,序列化就是把一个对象保存到一个文件或数
题目: 背景: 星期六给我班X姐布置了个集合方面的两个简单的题目,虽然布置了自己也没去看,她做的
序列化是将对象状态转换为可保持或传输的形式的过程。序列化的补集是反序列化,后者将流转换为对象
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号