网站首页 > 博客文章 正文
介绍
在本文中,我们会对 Optional 类进行一些说明,并且会解释下如果在使用 Optional 类的时候可能在 Jackson 中进行序列化和反序列化的过程中出现的问题。
针对上面的问题,本文会将会介绍在 Jackson 中如何处理 Optional 对象,和如果 Optional 对象可能出现潜在的 Null 的解决方案。
问题概览
首先让我们来看看如果使用 Jackson 来对 Optional 数据类型进行序列化和反序列化中出现的问题。
Maven 依赖
针对 Jackson,我们可以使用最新的版本。
当我们对本文进行更新的时候,jackson-core 的最新版本为 2.17.0。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.3</version>
</dependency>
定义 Book 对象
随后让我们来定义一个 Book 对象,在 Book 对象中,我们有一个使用 Optional 的字段。
当然在这个 Book 对象中,我们还需要添加 Getter 和 Setter 方法,在文章中,我们就省略到这些方法了。
public class Book {
private String title;
private Optional<String> subTitle;
}
在的对数据对象进行初始化的时候,我们需要注意对 Optional 对象设置值的方式,因为不同的值会影响序列化和反序列化的情况。
序列化
让我们先来实例化 Book 这个对象:
Book book = new Book();
book.setTitle("Oliver Twist");
book.setSubTitle(Optional.of("The Parish Boy's Progress"));
随后,我们使用 Jackson 的 ObjectMapper 方法来对实例化后的对象进行序列化,我们使用下面的代码来进行序列化:
String result = mapper.writeValueAsString(book);
从输出的字段中,我们可以看到输出的字符串内容中并没有输出具体的值,而是输出为下面的内容:
{"title":"Oliver Twist","subTitle":{"present":true}}
尽管上面的输出看起来有点奇怪,但是上面的输出却是正确的情况,因为这个和 Optional 的特性是有关的。
方法 isPresent() Optional 的 public getter 方法,这就意味着在序列化的时候基于我们对象中存储的具体的值,Jackson 将会输出 True 或者 False 。
这是 Jackson 当前正确的输出方式。
但,我们可能考虑在输出的时候输出具体的值,至于怎么输出这个具体的值的方法,我们在后续的解决方案中提出。
反序列化
现在,让我们使用上面的代码来对对象数据进行反序列化,考察使用下面的代码:
@Test(expected = JsonMappingException.class)
public void givenFieldWithValue_whenDeserializing_thenThrowException
String bookJson = "{ \"title\": \"Oliver Twist\", \"subTitle\": \"foo\" }";
Book result = mapper.readValue(bookJson, Book.class);
}
当上面的代码运行的时候将会提示下面的错误信息:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.util.Optional` (no Creators, like default constructor, exist): no String-argument constructor/factory method to deserialize from String value ('foo')
at [Source: (String)"{ "title": "Oliver Twist", "subTitle": "foo" }"; line: 1, column: 40] (through reference chain: com.ossez.jackson.optionalwithjackson.Book["subTitle"])
上面的错误信息针对 Jackson 来说是正确的,因为 Jackson 是需要一个构造方法来把 subtitle 参数的值来对 Optional 对象进行数据初始化。
解决方案
我们希望的是 Optional 对象应该把一个空的数据设置为 null,如果不是空的数据,Optional 应该使用值来进行处理。
针对上面的要求,Jackson 已经提供了解决方案,Jackson 针对 JDK8 的新增模块设置了一系列数据类型,这里就包括了 Optional。
Maven 依赖
首先,我们需要使用针对 JDK 8 使用的依赖,这个依赖的名称为:jackson-datatype-jdk8
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.17.0</version>
</dependency>
现在,我们需要把上面的依赖注册到 ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
或者上面的 2 句话也可以简化成 1 句话:
ObjectMapper mapper = new ObjectMapper().registerModule(new Jdk8Module());
序列化
现在,让我们来进行测试。
让我们再次使用上面的代码来对 Book 这个对象进行序列化和反序列化,然后我们在对输出的字符串进行查看。
Book book = new Book();
book.setTitle("Oliver Twist");
book.setSubTitle(Optional.of("The Parish Boy's Progress"));
String serializedBook = mapper.writeValueAsString(book);
assertThat(from(serializedBook).getString("subTitle"))
.isEqualTo("The Parish Boy's Progress");
如果我们尝试序列化一个空的 Book 对象的话,那么 Optional 字段中存储的数据为 null。
book.setSubTitle(Optional.empty());
String serializedBook = mapper.writeValueAsString(book);
assertThat(from(serializedBook).getString("subTitle")).isNull();
##反序列化
现在我们来进行反序列化,当我们进行反序列化的时候,我们可以看到上面的代码不再抛出 JsonMappingException 异常。
Book newBook = mapper.readValue(result, Book.class);
assertThat(newBook.getSubTitle()).isEqualTo(Optional.of("The Parish Boy's Progress"));
最后,我们再对上面的测试代码进行测试,从上面的代码代码输出中我们也可以看到没有异常,同时我们还得到了一个空的 Optional 对象。
assertThat(newBook.getSubTitle()).isEqualTo(Optional.empty());
结论
本文对针对 JDK 8 的新特性中提供的一些数据模型进行一些说明。
Jackson 需要注册一个新的 jdk8 数据类型才能对数据进行处理。
因为 Optional 是 JDK 8 中提供的新的数据特性,因此我们对一些新的数据类型我们需要有一些了解。
同时,针对 Jackson 还是有必要保持 JDK 的版本一致性和尽量使用比较高的版本,这样就可以使用更多有关 Jackson 提供的功能。
猜你喜欢
- 2024-11-03 Java Lambda从入门到精通之二十二Optional类
- 2024-11-03 java8,你应该了解的新特性(空指针终结者:Optional 类)
- 2024-11-03 Java Optional使用指南(java.util.optional)
- 2024-11-03 Java 8 Optional 最佳指南(java中optional)
- 2024-11-03 「Java8实战」使用Optional取代null
- 2024-11-03 Java Optional类的使用(java options类)
- 2024-11-03 Java8新特性:Optional 类(java options类)
- 2024-11-03 惊了,JDK都到23了,据说还有99%Java程序员都不会用optional?
- 2024-11-03 还在用if(obj!=null)做非空判断?带你快速上手Optional实战
- 2024-11-03 JDK8中新增的Optional工具类真的很好用哦,建议收藏
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)