首页 \ 问答 \ 为什么Jackson的ObjectMapper方法采用原始的TypeReference(Why Jackson’s ObjectMapper methods take raw TypeReference)

为什么Jackson的ObjectMapper方法采用原始的TypeReference(Why Jackson’s ObjectMapper methods take raw TypeReference)

Jackson 2 ObjectMapper类定义了许多用于将JSON字符串,字节数组,文件等反序列化为给定Java类型的通用方法。

目标类型在这些方法的参数中给出。

例如。 类型可以作为Class<T> ,就像在方法中一样

public <T> T readValue(String content, Class<T> valueType)

它返回相同的T对象(因此是类型安全的)。

但它也可以作为TypeReference<T> (可以编码复杂的泛型类型)给出,因此可以构建例如。 new TypeReference<List<Long>> { }告诉ObjectMapper需要将输入反序列化为longs列表 - 例如,可以传递它。 进入方法:

@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)

但是该方法采用原始 TypeReference而不是通用TypeReference<T> ,因此需要手动向调用添加泛型参数:

objectMapper.<List<Long>>readValue(input, listOfLongs)

如果在提供的类型中出错,编译器就无法捕获它。 如果方法签名是,那将不是问题

public <T> T readValue(String content, TypeReference<T> valueTypeRef)

这将告诉编译器返回的值始终与提供的TypeReference的泛型参数的类型相同,类似于它与Class<T>

我的问题是 - 这种API背后的原因是什么? 为什么Jackson方法采用原始TypeReference ? 当返回的对象实际上是TypeReference的泛型参数引用的不同类型时,是否存在任何有效的情况?

PS:还有什么让我感到困惑的是,相应的convertValue方法不是原始类型,而是通配符:

public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)

和类似的readValues

public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef)

readValue(JsonParser, TypeReference)实际上采用了一个完全限定的泛型参数

public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef)

Jackson 2 ObjectMapper class defines numerous generic methods for deserializing JSON strings, byte arrays, files, etc. to given Java types.

Target type is given in an argument to those methods.

Eg. a type may be given as a Class<T>, like in the method

public <T> T readValue(String content, Class<T> valueType)

which returns the same T object (and thus is type-safe to use).

But it may also be given as a TypeReference<T> (which can encode a complex generic type), so one can build eg. new TypeReference<List<Long>> { } to tell ObjectMapper that the input needs to be deserialized into a list of longs – it can be passed eg. into the method:

@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)

But that method takes raw TypeReference and not a generic TypeReference<T>, and thus one needs to manually add a generic parameter to the call:

objectMapper.<List<Long>>readValue(input, listOfLongs)

and if one makes a mistake in the provided type, the compiler cannot catch that. That would not be a problem if the method signature was

public <T> T readValue(String content, TypeReference<T> valueTypeRef)

which would tell the compiler that the returned value is always of the same type as the generic parameter of provided TypeReference, similarly to how it works with Class<T>.

My question is – what is the reason behind such an API? Why do Jackson methods take raw TypeReference? Are there any valid cases when returned object is really of a different type that that referenced by generic parameter of TypeReference?

PS: What also puzzles me is that a corresponding convertValue method takes not a raw type, but a wildcard one:

public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)

and similarly readValues:

public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef)

and the readValue(JsonParser, TypeReference) actually takes a fully qualified generic parameter:

public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef)

原文:https://stackoverflow.com/questions/48401520
更新时间:2023-01-23 06:01

最满意答案

它已被报告为一个问题 ,但被标记为3.x

图书馆的作者发表了一条评论,解释了为什么还没有纠正这个问题:

看起来像ObjectMapper API(也可能是ObjectReader )省略了与TypeReference类型变量匹配。 这对改变是有意义的,但可能会导致一些源兼容性问题(不是二进制),所以也许在3.0而不是更早的时候这样做。


It is already reported as an issue, but was labeled as 3.x.

There's a comment by the author of the library that explains why this hasn't been corrected yet:

Looks like ObjectMapper API (and perhaps ObjectReader too) omits type-variable matching with TypeReference. This would make sense to change, but is likely to cause some source-compatibility issues (not binary), so perhaps do this in 3.0 and not earlier.

相关问答

更多

相关文章

更多

最新问答

更多
  • Apache HttpClient(4.1和更新版本):如何进行基本身份验证?(Apache HttpClient (4.1 and newer): how to do basic authentication?)
  • 复选框不适用于模态(Checkbox does not work in modal)
  • 当使用大标题无法正常工作时,iOS 11会滚动到顶部(iOS 11 scroll to top when using large titles doesn't work properly)
  • 为什么我的Arduino不能超过10?(Why can't my Arduino compare above 10?)
  • 从Lib中删除PDB文件/功能(Remove the PDB file/functionality from Lib)
  • rails-2.3.5和rack-1.0.1的来源在哪里?(Where are the sources for rails-2.3.5 and rack-1.0.1?)
  • 如何使用List <>成员不可变的类?(How to make a class with List<> member immutable?)
  • Microsoft Edge popup扩展如何获取后台页面?(Microsoft Edge popup extension how to get backgroundpage?)
  • python删除中文unicode字符串之间的空格,但不删除英文单词之间的空格(python to remove space between Chinese unicode strings but not between English words)
  • SBT:如何Dockerize一个胖罐子?(SBT: How to Dockerize a fat jar?)
  • 如何从服务器请求中保存图像的分区以便以后合并(How to save segements of image in memory from server request for merging later)
  • python这段程序中a=self.[:]是什么意思 self一般用法是啥
  • ActiveRecord :: StatementInvalid:PGError:错误:关系“指令”不存在(ActiveRecord::StatementInvalid: PGError: ERROR: relation “instructions” does not exist)
  • 虚拟机安装kail linux最低配置是多少?
  • fread()中的空字符和c中的strncpy()(Null character in fread() and strncpy() in c)
  • 从ShutdownHook中查找程序退出的原因(Find, from a ShutdownHook, why a program exits)
  • 每天在固定时间运行任务(Run a task at fixed time everyday)
  • 电脑开不了机了,开机后进了桌面,显示WINDOWS BOOT MANAGER
  • 获取字符串第n个出现的索引?(Get the index of the nth occurrence of a string?)
  • python selenium 怎么打开 Chrome 并且能设置代理,请问可以指导小弟一下吗。
  • 错误:imagecopymerge()期望参数2是资源(Error: imagecopymerge() expects parameter 2 to be resource)
  • 在我的代码中,“无法找到可安装的ISAM”错误的原因是什么?(What could be the cause of 'Could not find installable ISAM' error in my code?)
  • Access 2013 - 没有自动编号的顺序编号(Access 2013 - sequential numbering without autonumber)
  • 将带有函数的Javascript对象转换为字符串(Converting a Javascript Object with Functions into a String)
  • Java中实现封装与信息隐藏与抽象与隐藏数据的比较(Practical example Encapsulation vs Information Hiding vs Abstraction vs Data Hiding in Java)
  • 不要包必须匹配java文件所在的子目录吗?(Don't packages have to match the subdirectories the java file is in?)
  • PyCharm Python控制台中的文件路径错误(File path wrong in PyCharm Python Console)
  • 在数据框列上应用curve_fit(Apply curve_fit on dataframe columns)
  • Java中的DateTime.FromOADate()相当于什么(Java中的Datetime是Datetime的两倍)(What is the equivalent of DateTime.FromOADate() in Java (double to Datetime in Java))
  • 给定DCEL,其中双胞胎等于下一个边缘,细分可以有多少面?(Given a DCEL where the twin is equal to the next of an edge, how many faces can the subdivision have?)