`
bit1129
  • 浏览: 1068116 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

 
阅读更多

在下面这个例子中,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 枚举类型的统一序列化/反序列化处理

    然而,在使用Gson库进行JSON序列化和反序列化时,枚举处理默认方式可能无法满足所有需求。本篇文章将详细探讨如何通过自定义Gson适配器实现枚举类型的统一序列化和反序列化处理,无需预先定义枚举,也无需修改Gson...

    Gson 中解决 json 反序列化时相同属性对应不同类型的值的问题(代码)

    Gson 中解决 json 反序列化时相同属性对应不同类型的值的问题(代码),对应文章链接:https://blog.csdn.net/ZiFung_Yip/article/details/89143255

    Gson解析之自定义序列化和反序列化

    本篇文章将深入探讨如何在使用Gson时进行自定义的序列化和反序列化,以及在遇到后端返回的数据类型与预期不符时的处理策略。 ### Gson自定义序列化 自定义序列化主要是为了在转换Java对象为JSON时,根据特定需求...

    C++ JSON 序列化与反序列化

    本篇文章将深入探讨C++中JSON的序列化与反序列化。 **一、JSON序列化** 序列化是指将C++的对象转换为JSON字符串的过程,以便在网络上传输或保存到文件中。常见的C++ JSON序列化库有RapidJSON、nlohmann/json、...

    fastJosn Gson Jackson 序列化和反序列化所需要的jarlib.rar

    在Java开发中,序列化和反序列化是数据转换的重要环节,主要用于将对象转换为可存储或传输的数据格式,如JSON字符串,以及将这些数据还原为原来的对象。本压缩包包含fastJson、Gson和Jackson这三种流行JSON库的jar...

    C#和Java的序列化反序列化

    Java中,除了基本的序列化机制,还有许多第三方库如Jackson、Gson等,它们提供了更高效、更灵活的JSON序列化和反序列化功能。例如,Jackson库的`ObjectMapper`类能够方便地将Java对象转换为JSON字符串,反之亦然。 ...

    Json反序列化

    四、JSON反序列化的步骤 1. 解析JSON字符串:将JSON格式的文本解析为解析树或者字典结构。 2. 转换为本地对象:根据解析树或字典,创建并填充目标对象的属性。 3. 处理异常:在转换过程中,如果JSON格式有误,反序列...

    fastjson、gson、jackson序列化和反序列化所用 json

    Gson的主要功能是通过`Gson.toJson()`方法实现对象到JSON的序列化,以及`Gson.fromJson()`方法实现JSON到对象的反序列化。Gson还支持自定义类型转换器,可以满足定制化的需求。 3. **Jackson**:Jackson是由...

    序列化与反序列化

    JSON序列化和反序列化库,如Jackson、Gson或org.json库,可能会在这个Demo中被使用。 例如,Jackson库提供了一个简单易用的API,可以通过`ObjectMapper`类实现JSON与Java对象之间的转换。要序列化一个Java对象,...

    反序列化利用工具ShiroExploit.V2.51.7z

    《反序列化利用工具ShiroExploit.V2.51详解》 在信息安全领域,漏洞利用是攻防对抗的关键一环。反序列化利用是一种高级的攻击手段,它利用了程序在处理序列化数据时的逻辑缺陷,可以导致远程代码执行、权限提升等...

    Java Json序列化与反序列化

    总结,Java中的JSON序列化与反序列化是数据交互的重要环节,Jackson和Gson是两个常用的库,它们提供了丰富的功能和良好的API设计,使得处理JSON数据变得简单高效。通过理解和掌握这些知识,开发者可以更好地在Java...

    Android-Android上的Java对象反序列化

    四、反序列化安全问题 1. **代码执行漏洞**: 不安全的反序列化可能导致远程代码执行。攻击者可以通过构造恶意序列化数据来触发特定的类加载和方法调用,执行任意代码。 2. **信息泄露**: 如果不正确处理反序列化,...

    序列化反序列化大集中

    而"工具"可能指的是各种序列化库,如Gson(Java),Newtonsoft.Json(C#)或protobuf(跨平台),这些工具简化了序列化和反序列化操作,提供了丰富的功能和灵活性。 在文件名列表中提到的"com"可能是Java的包名前缀...

    序列化工具(Gson, Jackson, FastJson, ProtoBuf)

    在这个主题中,我们将深入探讨四种常用的序列化工具:Gson, Jackson, FastJson和ProtoBuf,以及与ProtoBuf相关的`proto.exe`工具。 1. Gson(Google Gson): Gson是由Google提供的Java库,用于将Java对象转换为...

    Java 多次序列化对象到同壹個文件及反序列化的问题

    4. **使用版本控制的序列化策略**:例如,使用JSON库(如Jackson或Gson)进行序列化,这些库通常能更好地处理类结构的变化,同时支持版本控制,允许在反序列化时兼容旧版本的数据格式。 5. **持久化存储的替代方案*...

    Java对象的序列化和反序列化实践

    除此之外,还有一些第三方库,如Google的Gson和Jackson,它们提供了更灵活的序列化和反序列化功能,支持JSON等格式。 **源码分析** `ObjectSaver.java`可能包含了实现序列化和反序列化的示例代码。通过阅读和理解...

    Json序列化与反序列化详解

    本文将深入探讨JSON的序列化与反序列化过程,以及如何使用Gson、FastJson和Jackson这三种流行的Java库来实现这一功能。 一、什么是JSON序列化与反序列化? 1. JSON序列化:序列化是指将Java对象转换为JSON字符串的...

    gson源码与文档,集成多枚举类型统一序列化/反序列化处理

    本文将深入探讨如何利用Gson库进行多枚举类型的统一序列化和反序列化处理,以此避免为每个枚举类型单独创建Adapter。 首先,我们需要了解Gson的基本用法。Gson的核心类是`Gson`,它提供了`toJson()`和`fromJson()`...

    序列化与反序列化经典例子

    5. **序列化框架**:除了标准的Java序列化机制,还有许多高级的序列化库,如Jackson、Gson、protobuf等,它们提供了更灵活的配置和更好的性能。 在实际项目中,理解并熟练掌握序列化和反序列化对于开发高效、安全的...

    kotlin gson反序列化默认值失效深入讲解

    Gson反序列化默认值失效深入讲解 Gson反序列化是一种常用的数据序列化和反序列化技术,它广泛应用于 Android 开发、Web 开发等领域。然而,在使用 Gson 进行反序列化时,可能会出现默认值失效的问题,本文将深入...

Global site tag (gtag.js) - Google Analytics