当前位置: 首页 > 面试题库 >

扩展时,Jackson TypeReference是否起作用?

柯振濂
2023-03-14
问题内容

以下摘录是不言而喻的。您可以看到类型信息没有被擦除,但是映射器没有得到类型信息。我的猜测是杰克逊不允许这样做,对吧?如果我直接传递TypeReference,它将正确反序列化。

public class AgentReq<T> extends TypeReference<AgentResponse<T>> {...}

mapper.readValue(reader, new AgentReq<Map<String, Set<Whatever>>>());

如果这样做,它也将不起作用:

public class AgentReq<T> {

    public TypeReference<AgentResponse<T>> getTypeRef() {
        return new TypeReference<AgentResponse<T>>() {};
    }
}

mapper.readValue(reader, new AgentReq<Map<String, Set<Whatever>>>()).getTypeRef();

我正在使用2.1.5版。

编辑:供将来参考,在解决问题时不要低估TypeReference构造函数。在这里,您可以直接查看它是否能够检索类型信息。答案是否定的,您不能扩展TypeReference并期望它能工作,甚至不能重写其getType()方法并向其提供从类中解析的类型信息,因为您所能获得的只是getClass()。
getGenericSuperClass()…你不能做getClass()。getGenericClass()


问题答案:

您需要了解TypeReference作品的运作方式。为此,我们进入源代码

protected TypeReference()
{
    Type superClass = getClass().getGenericSuperclass();
    if (superClass instanceof Class<?>) { // sanity check, should never happen
        throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
    }
    ...
    _type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}

Class#getGenericSuperclass()javadoc的状态

返回表示该类表示的实体的直接超类的Type(类,接口,原始类型或void)。

如果超类是参数化类型,则返回的Type对象必须准确反映源代码中使用的实际类型参数。

换句话说,如果我们能够做到new TypeReference()(我们不能做到,那是抽象的),它将返回Class该类的实例Object。但是,使用匿名类(从类型扩展)

new TypeReference<String>(){}

创建的实例的直接超类是参数化类型TypeReference,根据javadoc,我们应该获得一个Type实例,该实例可以
准确反映源代码中使用的实际类型参数

TypeReference<String>

然后您可以从中获得参数化类型getActualTypeArguments()[0]),并返回String

让我们以使用匿名类和子类进行可视化为例

public class Subclass<T> extends TypeReference<AgentResponse<T>>{
    public Subclass() {
        System.out.println(getClass().getGenericSuperclass());
        System.out.println(((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }
}

跑步

new Subclass<String>();

版画

com.fasterxml.jackson.core.type.TypeReference<Test.AgentResponse<T>>
Test.AgentResponse<T>

符合javadoc规则。Test.AgentResponse<T>是源代码中实际的参数化类型。现在,如果相反,我们有

new Subclass<String>(){}; // anonymous inner class

我们得到结果

Test.Subclass<java.lang.String>
class java.lang.String

这也符合要求。现在,内部类直接从源类中扩展了,该内部类Subclass由其参数进行参数化String

您会注意到,使用Subclass匿名内部类,我们丢失了有关AgentResponse泛型类型的信息。这是不可避免的。

注意

reader = new StringReader("{\"element\":{\"map-element\":[{\"name\":\"soto\", \"value\": 123}]}}");
obj = mapper.readValue(reader, new AgentReq<Map<String, Set<Whatever>>>());

将编译并运行,但是类型AgentReq<Map<String, Set<Whatever>>>将丢失。Jackson将使用默认类型来序列化JSON。的element将被反序列化作为AgentResponse,而map- element将被反序列化作为Map和JSON数组作为ArrayList



 类似资料:
  • 问题内容: 我正在尝试使用协议扩展在某些方法上添加默认行为,例如: 您可能会猜到,键盘永远不会消失。我真的看不出问题出在哪里。这是语言限制吗?有人已经成功做到了吗? 编辑: 正如@Logan所建议的,默认协议的方法实现不适用于标记为的协议。但是,具有以下签名 我已经测试了默认的实现,它似乎运行良好: 问题答案: 我不能100%积极,但是我相信这是正在发生的事情: 无法从访问协议扩展。由于是协议,因

  • 问题内容: SASS具有一个称为的功能,该功能允许选择器继承另一个选择器的属性,但不复制属性(如mixins)。 LESS是否也具有此功能? 问题答案: 是的,Less.js推出的V1.4.0。 LESS没有实现SASS和Stylus使用的at- rule()语法,而是实现了伪类语法,这为LESS的实现提供了灵活性,使其可以直接应用于选择器本身或在语句内部。因此,这两个都将起作用: 要么 此外,您

  • 我也需要扩展WebMvcConfigurationSupport类,修改两个内容: 我喜欢从WebMvcAutoConfiguration类注册的默认值,但是由于类上的条件注释,当我扩展WebMvcConfigurationSupport类时,它会防止自动配置的发生。 提前道谢!

  • 我们使用SharePoint应用程序自定义操作为站点和OneDrive上的文档库中的文件自定义命令栏和上下文菜单。它同时在现代视图和经典视图上工作,只是在现代视图上有一个新的页面,而在经典视图上有一个弹出窗口。 最近,SharePoint应用程序自定义操作停止了对ODFB的现代视图的操作,但仍在对ODFB的经典视图和站点的现代/经典视图进行操作。我们被告知需要使用SPFx在modern view上

  • 我正在尝试慢慢地从Obj-C迁移到Swift。我的第一步是将小型、简单的方法迁移到Swift扩展,所以我决定尝试迁移但这并不起作用,因为它认为该方法是在我的Objective-C代码中的其他地方实现的。事实并非如此。 我使用的是Xcode 7.3(7D175) 以下是一些复制步骤: > 创建一个新的Obj-C项目。 创建一个新的空的Swift文件,名为。这也创建了一个桥接头文件。 添加到Bridi