如何在 Gson 中实现 TypeAdapterFactory?

     2023-02-22     215

关键词:

【中文标题】如何在 Gson 中实现 TypeAdapterFactory?【英文标题】:How do I implement TypeAdapterFactory in Gson? 【发布时间】:2014-04-13 23:34:16 【问题描述】:

如何在 Gson 中实现 TypeAdapterFactory 类型?

create 的主要方法是泛型的。为什么?

注册方法registerTypeAdapterFactory() 不接收类型参数。那么,Gson 是如何知道工厂处理了哪些类的呢?

我应该为多个类实现一个工厂,还是可以为多个类实现一个工厂?

如果我为多个类实现一个工厂,那么在域外类型参数的情况下我应该返回什么?

【问题讨论】:

【参考方案1】:

当您注册一个常规类型适配器 (GsonBuilder.registerTypeAdapter) 时,它只会为该特定类生成一个类型适配器。例如:

public abstract class Animal  abstract void speak(); 
public class Dog extends Animal 
   private final String speech = "woof";
   public void speak() 
       System.out.println(speech);
   


// in some gson related method
gsonBuilder.registerTypeAdapter(Animal.class, myTypeAdapterObject);
Gson g = gsonBuilder.create();
Dog dog = new Dog();
System.out.println(g.toJson(dog));

如果你这样做了,那么Gson使用你的myTypeAdapterObject,它将使用Object 的默认类型适配器。

那么,如何创建一个可以将任何Animal 子类转换为 Json 的类型适配器对象?创建一个TypeAdapterFactory!工厂可以使用泛型类型和TypeToken 类进行匹配。如果您的 TypeAdapterFactory 不知道如何处理该类型的对象,您应该返回 null。

TypeAdapterFactory 可用于的另一件事是您不能以任何其他方式链接适配器。默认情况下,Gson 不会将您的 Gson 实例传递给 TypeAdapterreadwrite 方法。所以如果你有一个像这样的对象:

public class MyOuterClass 
    private MyInnerClass inner;

如果不使用TypeAdapterFactory,就无法编写知道如何使用TypeAdapter<MyInnerClass>TypeAdapter<MyOuterClass>TypeAdapterFactory.create 方法确实传递了 Gson 实例,它允许您教您的 TypeAdapter<MyOuterClass> 如何序列化 MyInnerClass 字段。


一般来说,这是开始编写TypeAdapterFactory 实现的一个很好的标准方法:

public enum FooAdapterFactory implements TypeAdapterFactory 
    INSTANCE; // Josh Bloch's Enum singleton pattern

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) 
        if (!Foo.class.isAssignableFrom(type.getRawType())) return null;

        // Note: You have access to the `gson` object here; you can access other deserializers using gson.getAdapter and pass them into your constructor
        return (TypeAdapter<T>) new FooAdapter();
    

    private static class FooAdapter extends TypeAdapter<Foo> 
        @Override
        public void write(JsonWriter out, Foo value) 
            // your code
        

        @Override
        public Foo read(JsonReader in) throws IOException 
            // your code
        
    

【讨论】:

那么,Gson 会为序列化期间遇到的数百个类调用我的适配器工厂吗? 是的,但是Gson 保留了classAdapterFactory 的查找表,因此它只尝试您的课程一次。如果 create 返回 null 它永远不会再尝试该类。 @SuzanCioc 嗯,是的......我看源代码就知道了:-D 如果FooAdapter 是唯一可以提供的适配器,那么为什么要使用TypeAdapterFactory?为什么不直接使用TypeAdapter 因为TypeAdapter&lt;T&gt; 只能序列化一种特定类型,T。如果您想序列化一个接口和所有实现者,您需要在 Gson 查找表中为实现该接口的所有个请求的类创建一个引用。

如何在 laravel 中实现 vuetify?

】如何在laravel中实现vuetify?【英文标题】:Howtoimplementvuetifyinlaravel?【发布时间】:2018-07-2123:32:58【问题描述】:我是vuetify的新手,我试图在laravel中实现它。有人已经在laravel中实现了vuetify,可以告诉我怎么做吗?我已经安装... 查看详情

如何在android中实现BottomAppBar?

】如何在android中实现BottomAppBar?【英文标题】:howtoimplementBottomAppBarinandroid?【发布时间】:2020-12-2823:06:46【问题描述】:如何在android中实现BottomAppBar。build.gradleimplementation\'com.google.android.material:material:1.0.0-beta01\'activity_main 查看详情

如何在android中实现svm模型?

】如何在android中实现svm模型?【英文标题】:Howtoimplementsvmmodelinandroid?【发布时间】:2014-05-3121:47:13【问题描述】:我在Matlab中使用svmtrain训练了分类器,现在我不知道如何在android中实现模型。甚至没有一个例子来展示如何使用... 查看详情

如何在 Fragments 中实现 onBackPressed()?

】如何在Fragments中实现onBackPressed()?【英文标题】:HowtoimplementonBackPressed()inFragments?【发布时间】:2011-07-2320:22:18【问题描述】:有没有一种方法可以在AndroidFragment中实现onBackPressed(),类似于我们在AndroidActivity中的实现方式?由... 查看详情

如何在 exoplayer 中实现 OkHttpDataSourceFactory?

】如何在exoplayer中实现OkHttpDataSourceFactory?【英文标题】:HowdoyouimplementOkHttpDataSourceFactoryinexoplayer?【发布时间】:2020-12-0714:51:40【问题描述】:在exoplayer中如何实现OkHttpDataSourceFactory?【问题讨论】:【参考方案1】:我翻遍了,... 查看详情

如何在 Swift 中实现 NSWindowRestoration?

】如何在Swift中实现NSWindowRestoration?【英文标题】:HowtoimplementNSWindowRestorationinSwift?【发布时间】:2014-06-1000:50:12【问题描述】:我尝试在非基于文档的应用程序中在Swift中实现NSWindowRestoration协议。然而,restoreWindowWithIdentifier方... 查看详情

如何在 Scala 中实现 DAO?

】如何在Scala中实现DAO?【英文标题】:HowtoimplementDAOinScala?【发布时间】:2011-07-1819:24:50【问题描述】:我想在Scala中实现DAO,如下所示:traitDAO[PK,-T,-Q]//Tisa"valueobject",PKisaprimarykey,andQisqueryparameters.defcreate(t:T):Unitdefupdate(t:T):Unitdefr... 查看详情

如何在 Swift 中实现单例类

】如何在Swift中实现单例类【英文标题】:HowtoImplementSingletonclassinSwift[duplicate]【发布时间】:2016-02-1822:01:56【问题描述】:我是swift编程新手,请告诉我如何使用代码在swift中实现单例类。在obj-c中我知道+(id)sharedManagerstaticMediaMode... 查看详情

如何在 JavaScript 中实现锁

】如何在JavaScript中实现锁【英文标题】:HowtoimplementalockinJavaScript【发布时间】:2011-07-1719:55:47【问题描述】:如何在JavaScript中实现与C#中的lock等效的东西?所以,为了解释我的想法,一个简单的用例是:用户点击按钮B。B引发o... 查看详情

如何在矢量中实现按钮

】如何在矢量中实现按钮【英文标题】:Howtoimplementbuttoninavector【发布时间】:2012-12-0915:42:18【问题描述】:在我的桌子上。我想在我可以按下的每一行中放置一些按钮。但我不知道该怎么做publicstaticDefaultTableModelbuildTableModel(Resu... 查看详情

如何在颤动中实现这种效果/布局?

】如何在颤动中实现这种效果/布局?【英文标题】:Howtoachievethiseffect/layoutinflutter?【发布时间】:2021-10-0520:29:18【问题描述】:我发现,这种搜索效果是内置在ios框架中的。但是这种布局如何在Flutter中实现呢?【问题讨论】:... 查看详情

这是如何在 swift 4 中实现的?

】这是如何在swift4中实现的?【英文标题】:Howisthisimplementedinswift4?【发布时间】:2018-08-0413:25:33【问题描述】:我有这个link用于表格视图中的下拉搜索栏。我能够使用此代码在tableview中实现搜索栏searchController.searchResultsUpdater=s... 查看详情

如何在 RecyclerView 中实现 StartActivityForResult

】如何在RecyclerView中实现StartActivityForResult【英文标题】:HowtoimplementStartActivityForResultinRecyclerView【发布时间】:2018-07-1916:07:21【问题描述】:我正在尝试在我的RecyclerView中使用startActivityForResult并且不知道如何...尝试了这种方式... 查看详情

如何在 Chrome 中实现抓取光标图标?

】如何在Chrome中实现抓取光标图标?【英文标题】:HowcanyouimplementagrabbingcursoriconinChrome?【发布时间】:2011-04-0715:32:01【问题描述】:我知道可以在Chrome中使用抓取光标图标(当然是在Gmail中),但我不知道如何在我的代码中实现... 查看详情

如何在电子中实现延迟深度链接

】如何在电子中实现延迟深度链接【英文标题】:howtoimplementimplementdeferreddeeplinkinginelectron【发布时间】:2021-01-2623:54:16【问题描述】:试图找到有关如何在电子应用程序中实现延迟深度链接的信息,但在官方电子文档中找不到... 查看详情

如何在 Xamarin 中实现 SfMap

】如何在Xamarin中实现SfMap【英文标题】:HowcanIimplementSfMapinXamarin【发布时间】:2021-10-2514:22:03【问题描述】:如何在基于MVVM结构的项目中实现SfMaps?第一,我必须获取我当前的位置并将其显示在地图上,然后我必须将该标记点... 查看详情

如何在 Fragment 中实现 SearchView

】如何在Fragment中实现SearchView【英文标题】:HowtoimplementSearchViewinFragment【发布时间】:2016-02-2211:09:50【问题描述】:我写了以下代码:publicclassTabFragmentextendsFragment@OverridepublicvoidonCreateOptionsMenu(Menumenu,MenuInflaterinflater)super.on 查看详情

如何在 Kotlin 中实现 OnClickListener 接口? [复制]

】如何在Kotlin中实现OnClickListener接口?[复制]【英文标题】:HowtoimplementOnClickListenerinterfaceinKotlin?[duplicate]【发布时间】:2018-07-1322:39:02【问题描述】:如何在Kotlin中实现OnClickListener接口,就像我们在Java中一样,并处理像switchcase... 查看详情