首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

GSON多态反序列化无法使用RuntimeTypeAdapterFactory反序列化“Type`属性

GSON是Google提供的一个用于Java对象和JSON数据之间相互转换的库。在GSON中,多态反序列化是指将JSON数据转换为Java对象时,根据JSON数据中的特定属性值来确定具体的Java对象类型。

在使用GSON进行多态反序列化时,如果要使用RuntimeTypeAdapterFactory来反序列化包含"Type"属性的JSON数据,可能会遇到无法正常反序列化的问题。RuntimeTypeAdapterFactory是GSON库中的一个工厂类,用于根据特定属性值来确定具体的Java对象类型。

解决这个问题的方法是,首先需要创建一个自定义的TypeAdapterFactory,用于处理多态反序列化。然后,在自定义的TypeAdapterFactory中,根据JSON数据中的"Type"属性值来确定具体的Java对象类型,并进行相应的反序列化操作。

以下是一个示例代码,演示了如何使用自定义的TypeAdapterFactory来解决GSON多态反序列化无法使用RuntimeTypeAdapterFactory反序列化"Type"属性的问题:

代码语言:txt
复制
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;

public class PolymorphicDeserializerExample {
    public static void main(String[] args) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new CustomTypeAdapterFactory())
                .create();

        String json = "{\"Type\":\"Dog\",\"name\":\"Max\",\"age\":3}";
        Animal animal = gson.fromJson(json, Animal.class);
        System.out.println(animal);
    }

    // 自定义的TypeAdapterFactory
    static class CustomTypeAdapterFactory implements TypeAdapterFactory {
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (type.getRawType() == Animal.class) {
                return (TypeAdapter<T>) new AnimalTypeAdapter(gson);
            }
            return null;
        }
    }

    // 自定义的TypeAdapter
    static class AnimalTypeAdapter extends TypeAdapter<Animal> {
        private Gson gson;

        public AnimalTypeAdapter(Gson gson) {
            this.gson = gson;
        }

        @Override
        public void write(JsonWriter out, Animal value) throws IOException {
            // 不需要实现
        }

        @Override
        public Animal read(JsonReader in) throws IOException {
            in.beginObject();
            String type = null;
            while (in.hasNext()) {
                String name = in.nextName();
                if (name.equals("Type")) {
                    type = in.nextString();
                } else {
                    in.skipValue();
                }
            }
            in.endObject();

            if (type != null) {
                switch (type) {
                    case "Dog":
                        return gson.fromJson(in, Dog.class);
                    case "Cat":
                        return gson.fromJson(in, Cat.class);
                    // 可以根据具体的需求添加其他类型
                }
            }

            return null;
        }
    }

    // Animal类及其子类
    static class Animal {
        // 公共属性
        String name;
        int age;

        @Override
        public String toString() {
            return "Animal{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    static class Dog extends Animal {
        // Dog特有属性
        String breed;

        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", breed='" + breed + '\'' +
                    '}';
        }
    }

    static class Cat extends Animal {
        // Cat特有属性
        String color;

        @Override
        public String toString() {
            return "Cat{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", color='" + color + '\'' +
                    '}';
        }
    }
}

在上述示例代码中,我们首先创建了一个自定义的TypeAdapterFactory(CustomTypeAdapterFactory),用于处理Animal类的多态反序列化。然后,我们创建了一个自定义的TypeAdapter(AnimalTypeAdapter),在其中根据JSON数据中的"Type"属性值来确定具体的Java对象类型,并进行相应的反序列化操作。

最后,我们使用GSON的registerTypeAdapterFactory方法将自定义的TypeAdapterFactory注册到GSON实例中,然后使用fromJson方法将JSON数据转换为Animal对象。

需要注意的是,上述示例代码中的Animal类及其子类(Dog和Cat)是为了演示目的而创建的简单类,实际使用时需要根据具体的需求进行相应的定义。

希望以上内容能够帮助到您!如果有任何疑问,请随时提问。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Gson 系列文章

(founderArray.length); // 3 List 由于Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是...alternate 属性是用在反序列化上的,也就是说从 JSON 到 Java 类的过程。Gson 会帮我们匹配 JSON 中的命名,并尝试找到一个字段映射。..., isDeveloper=true, age=18, day=SUNDAY) 自定义枚举()序列化 使用 @SerializedName 注解给每个变量赋予另一个字段名: public enum Day2..., isDeveloper=true, age=18, day2=MONDAY) 通过结果可以看到枚举的()序列化使用,并配合 @SerializedName 来简化使用。...Advanced — 通过 @JsonAdapter 自定义()序列化 之前我们介绍了如何使用 Gson 来自定义()序列化和自定义实例创建。

15.6K10

穿越到东汉末年的Jackson

Gson: 吾观取汉上之地,易如掌。我主刘豫州躬行仁义,不忍夺同宗之基业,故力辞之。刘琮孺子,听信佞言,暗自投降,致使曹操得以猖獗。...例如,ExtendableBean实体具有name属性和一组键/值对形式的可扩展属性: image.png 当我们序列化这个实体的一个实例时,我们将Map中的所有键值作为标准的、普通的属性: image.png...@JsonPropertyOrder 我们可以使用 @JsonPropertyOrder注释来指定序列化属性的顺序。...让我们为MyBean实体的属性设置自定义顺序: 这是序列化的输出: image.png @JsonRootName 该 @JsonRootName注释时,如果包裹被启用,以指定的包装中使用的根目录的名称...我们将使用 @JsonSerialize通过CustomDateSerializer序列化eventDate属性: image.png 这是简单的自定义 Jackson 序列化程序: image.png

2K20
  • DSL-JSON参数走私浅析

    当遇到斜杠 \(转义字符)时。...否则,退出循环: 也就是说,WeakHash主要跟反序列化过程中匹配的属性有关。...方法计算最终的哈希值并复制属性名称 这里有一个比较关键的节点是,当遇到斜杠\时,不会进一步对类似Unicod等字符进行额外的处理,直接跳过下一个字节。...那么是否说明当使用这种方式进行JSON解析时,无法识别Unicode编码的key呢?...例如上面的例子,由于无法识别自定义类型属性key的Unicode编码,对于下面的JSON重复键值内容只能取前者123,而其他解析器则默认获取后者,这里存在解析差异,在特定情况下可以达到参数走私的效果,在日常代码审计过程中需要额外的关注

    19210

    用了几年的 Fastjson,我最终替换成了Jackson!

    jackson1是已经过时的框架,因此可以忽略,cheshire和json-simple排名尚且不如fastjson,也忽略,剩余jackson2、gson以及org.json,其中org.json的使用量...classes、interfaces属性的AUTO Type,但是该特性容易导致安全漏洞,强烈建议使用ObjectMapper.disableDefaultTyping()设置为只允许@JsonTypeInfo...字母顺序排序,等价于jackson的@JsonPropertyOrder.alphabetic() boolean alphabetic() default true; // 反序列化多态类型时...,如果根据其他typeName等方式无法找到正确的子类时,默认使用的子类,等价于jackson的@JsonTypeInfo.defaultImpl() Class builder() default Void.class; // 声明这个类型的别名,反序列化多态类型时使用,等价于jackson的@JsonTypeName String typeName

    5.3K10

    含有泛型的 JSON 反序列化问题

    含有泛型的 JSON 反序列化 一、背景 二、分析 2.1 事出诡异必有妖 三、解决之道 3.1 猜想验证 3.2 举一三 四、总结 一、背景 今天无聊之园提了一个问题,涉及的示例大致如下:...有人说“由于泛型擦除,没有泛型信息,所以无法逆向构造回原有类型”。...因此如果能够通过某种途径,告诉它泛型的类型,就可以帮助你反序列化成真正的类型。...因此我们使用 TypeReference 并不仅仅是为了消除警告,而是为了告知 fastjson 泛型的具体类型,正确反序列化泛型的类型。 那么底层原理是啥呢?...T) parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features); } 3.2 举一

    3.1K41

    除了FastJson,你还有选择: Gson简易指南

    Gson 基本使用 使用 Gson 框架进行序列化与反序列操作,都离不开 com.google.gson.Gson 对象,它也是 Gson 框架的关键对象,提供的公共 API 具备了多种序列化和反序列方式...简单对象的反序列化 现在我们再来看下 JSON 反序列化成 Java 对象用法,这里主要使用方法是 com.google.gson.Gson#fromJson,它最基础的用法就是 fromJson(String...那又该如何处理呢, 我们需要使用 Gson 的 另外一个 fromJson 方法:fromJson(String json, Type typeOfT) ,先看下使用方式 @Test public void...而这里 TypeToken 是 Gson 为了支持泛型而引入的类,来解决 Java 无法提供泛型类型表示的问题,由于 TypeToken 的构造方法是protected修饰的,无法直接构造,使用就需要写成...@Expose 这个注解只能用在字段上,作用就是注明对应的字段是否将在序列化或者反序列化时暴露出来,有两个属性 serialize 和 deserialize ,默认都为 true。

    1.3K30

    除了FastJson,你还有选择: Gson简易指南

    [006y8mN6gy1g6s3u2bfxxj30oa0ewwfn.jpg] Gson 基本使用 使用 Gson 框架进行序列化与反序列操作,都离不开 com.google.gson.Gson 对象,它也是...简单对象的反序列化 现在我们再来看下 JSON 反序列化成 Java 对象用法,这里主要使用方法是 com.google.gson.Gson#fromJson,它最基础的用法就是 fromJson(String...那又该如何处理呢, 我们需要调用 Gson 的 另外一个 fromJson 方法:fromJson(String json, Type typeOfT) ,先看下使用方式 @Test public...而这里 TypeToken 是 Gson 为了支持泛型而引入的类,来解决 Java 无法提供泛型类型表示的问题,由于 TypeToken 的构造方法是protected修饰的,无法直接构造,使用就需要写成...@Expose 这个注解只能用在字段上,作用就是注明对应的字段是否将在序列化或者反序列化时暴露出来,有两个属性 serialize 和 deserialize ,默认都为 true。

    1.6K40

    面试长知识了!Java 关键字 transient 竟然还能这么用

    约定二、被 transient 关键字修饰过的属性不能被序列化,也就是说被 transient 修饰过的属性,在对对象序列化后,是无法访问到该属性的。...{"amounts":3,"price":2} 我们看到,sum 属性被 transient 修饰后,是不会被 Gson 序列化输出的,这里就引出了使用 transient 关键字一个很重要的概念:对象属性推导...对象属性推导 “如果一个对象的属性值可以通过其他属性或者方法推理出来的,那么该属性就没必要被序列化了。 借此我们以 Gson 来分析被 transient 修饰过的属性不能被序列化过程。...从上面的这两种序列化方式,我想你已经看到了,使用 Exteranlizable 接口实现序列化时,我们自己指定那些属性是需要序列化的,即使是 transient 修饰的。...transient 关键字总结 通过常用的 Gson 方式来验证 tranient 关键字不能序列化使用场景。

    2.2K41

    Jackson常用注解详解1 初级2 中级

    1 初级 我们从几个简单的使用场景开始:重命名属性,忽略属性,以及修改属性使用的类型。...注意 下面的例子仅仅显示了成员属性,注解同样也可以用在成员方法(getter/setter)上 ①属性重命名时使用的注解 最常见的使用方式之一就是改变某个成员属性使用的JSON名称,例如: public...在有些情况下,Jackson在读入或输出一个成员属性时,所选用的类型可能并不是你想要的: 当读取(反序列化)时,声明的类型可能是一个基本类型,但是你确切地知道应该使用的实现类型(ps:也就说,我们需要反序列化后生成的对象是实现类型的...②处理多态类型(polymorphic types) 如果你要进行读取、输出操作的对象拥有许多可能的子类型(即表现出多态性),你可能还需要添加一些类型信息。...I(ntro to polymorphic type handling) ③重新设置属性的自动发现(Changing property auto-detection) Jackson默认的属性发现规则将会查找到如下所述的属性

    1.5K61

    Android 序列化框架 Gson 原理分析,可以优化吗?

    序列化时,首先使用反射获取字段值,再使用字段的 BoundFiled 序列化; 在反序列化时,首先创建对象实例(下文会讨论如何创建),再使用依次使用字段的 BoundField 反序列为字段类型的值,...由于 Java 有泛型擦除,无法直接在 .class 语法上声明泛型信息,Gson 的方法是要求程序员创建匿名内部类,由 Gson 在运行时通过反射获取类声明上的泛型信息。...>(jsonStr, token.type) 为什么反序列化泛型类要使用匿名内部类呢?...原理是 Class 文件中的 Signature 属性会保持类签名信息,而 TypeToken 只是一个工具类,内部通过反射获取类签名中泛型信息并返回 Type 类型。...在 Gson 的反序列化中,首次反序列化一个类型的对象时,Gson 需要使用大量反射调用解析一个 TypeAdapter 适配器对象。随着 Model 的复杂程度增加,首次解析的耗时会不断膨胀。

    2.3K50

    Google Gson用法详解

    注解包含属性 value –序列化或反序列化时所需的字段名称。 alternate–反序列化时字段的备用名称。除了“值”属性外,它还提供了更多可能的名称。...如果有多个字段匹配一个属性,则Gson使用最后处理的那个。 9.2、序列化期时更改字段名称 让我们以只有四个字段的Employee类为例。...不过,我们可能会遇到默认和内置自定义选项无法解决我们问题的情况。在这种情况下,我们可以通过两个接口JsonSerializer和JsonDeserializer使用自定义序列化和反序列化。...} 为Json创建自定义序列化程序后,我们还需要通过GsonBuilder.registerTypeAdapter(Type,Object)注册该序列化程序。...Json创建自定义反序列化器之后,我们还需要通过GsonBuilder.registerTypeAdapter(Type,Object)注册此反序列化器。

    21.9K31

    gson 替换 fastjson 引发的线上问题分析

    ,这可就要命了,我相信很多小伙伴也是不胜其苦,考虑了使用其他序列化框架替换 fastjson。...问题描述 线上一个非常简单的逻辑,将对象序列化成 fastjson,再使用 HTTP 请求将字符串发送出去。...当单个重复对象的数量非常多,以及单个对象的提交较大时,两种不同的序列化策略会导致一个质变,我们不妨来针对特殊的场景进行下对比。 压缩比测试 序列化对象:包含大量的属性。以模拟线上的业务数据。...使用基准测试可以精准地测试出各个序列化方式的吞吐量。...具有非常强大的序列化压缩比,适合大报文序列化后供网络传输的场景使用 以笔者的测试 case 为例,fastjson 具有非常高的吞吐量,对得起它的 fast,适合需要高吞吐的场景使用 序列化还需要考虑到是否支持循环引用

    1.7K20

    gson 替换 fastjson 引发的线上问题分析

    ,这可就要命了,我相信很多小伙伴也是不胜其苦,考虑了使用其他序列化框架替换 fastjson。...问题描述 线上一个非常简单的逻辑,将对象序列化成 fastjson,再使用 HTTP 请求将字符串发送出去。原本工作的好好的,在将 fastjson 替换为 gson 之后,竟然引发了线上的 OOM。...当单个重复对象的数量非常多,以及单个对象的提交较大时,两种不同的序列化策略会导致一个质变,我们不妨来针对特殊的场景进行下对比。 压缩比测试 序列化对象:包含大量的属性。以模拟线上的业务数据。...使用基准测试可以精准地测试出各个序列化方式的吞吐量。...具有非常强大的序列化压缩比,适合大报文序列化后供网络传输的场景使用 以笔者的测试 case 为例,fastjson 具有非常高的吞吐量,对得起它的 fast,适合需要高吞吐的场景使用 序列化还需要考虑到是否支持循环引用

    83820

    Gson - 两种字段,一种解析

    SerializedName(value = "inContent", alternate = {"outContent"}) private String content; private String type...; @SerializedName("@timestamp") private String timestamp; } @SerializedName的value属性序列化和反序列化的字段名称...gson = new Gson(); 从字符串转换成实体实体类的过程就是反序列化: // 输出req1和req2的content,均为Hello World // str1有inContent属性,所以直接将它的值赋给...,value属性的inContent参与了序列化和反序列化,alternate里面的备胎outContent只参与了反序列化。...查找多处资料后,发现 alternate只有在2.4版本之后才能使用 本地使用Gson2.8,并且将依赖打进了jar包,但是flume中lib下居然有个gson-2.2.2.jar(奔溃中...)

    55420

    Spring Boot 之使用 Json 详解

    Spring Boot 提供了 Gson 的自动配置。当 Gson 在 classpath 上时,会自动配置 Gson bean。提供了几个 spring.gson.* 配置属性来自定义配置。...如果使用 @RestController 注解 Controller,则 Controller 中的方法无法返回 jsp 页面,或者 html,配置的视图解析器 InternalResourceViewResolver...指定类的 Json 序列化、反序列化 如果使用 Jackson 序列化和反序列化 JSON 数据,您可能需要编写自己的 JsonSerializer 和 JsonDeserializer 类。...@JsonTest 使用 @JsonTest 可以很方便的在 Spring Boot 中测试序列化、反序列化。...GSON 配置 当 Spring Boot 的 json 库为 gson 时,可以使用以下配置属性(对应 GsonProperties 类): spring.gson.date-format= # Format

    4.1K10
    领券