Jackson序列化和反序列化Optional类型字段

177 阅读2分钟

声明: 此文章内容大部分来自于 www.baeldung.com/jackson 此系列文章,个人在其基础上作了一点改动,原文在外网,翻译放到此处仅仅作为分享,如涉及版权问题,请联系我删除。

学习Jackson的原因

因为SpringBoot选用了Jackson序列化Json数据,因此为了日常开发过程中避免踩坑,还是需要花点时间认真学习一下的。

这篇文章主要是学习一下如何使用Jackson序列化和反序列化 Optional 类型的字段。

Jackson在最新版本(2.17.2)支持注册第三方扩展模块来扩展功能,Jackson默认是不支持序列化Optional类型的字段的,我们先看一下Jackson的默认行为。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>2.17.2</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
</dependencies>

public class OptionalFieldTest {

    @Test
    public void testSerializeOptionalField() throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        OptionalField optionalField = new OptionalField();
        optionalField.setName("Alice");
        optionalField.setOptionalAge(Optional.of(25));

        String jsonString = mapper.writeValueAsString(optionalField);
        System.out.println(jsonString);

    }


    private static class OptionalField {
        private String name;
        private Optional<Integer> optionalAge;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Optional<Integer> getOptionalAge() {
            return optionalAge;
        }

        public void setOptionalAge(Optional<Integer> optionalAge) {
            this.optionalAge = optionalAge;
        }
    }

}

结果如下

image.png

反序列化也会报此异常,它会提示你引入 jackson-datatype-jdk8解决此问题,我们按其提示来试一下。 首先是新增一个依赖

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>2.17.2</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.11.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.11.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

然后修改一下测试用例

public class OptionalFieldTest {

    @Test
    public void testSerializeOptionalField() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        // 注意下面这一行代码,注册Jdk8Module
        mapper.registerModule(new Jdk8Module());

        OptionalField optionalField = new OptionalField();
        optionalField.setName("Alice");
        optionalField.setOptionalAge(Optional.of(25));

        String jsonString = mapper.writeValueAsString(optionalField);
        System.out.println(jsonString);

    }


    private static class OptionalField {
        private String name;
        private Optional<Integer> optionalAge;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Optional<Integer> getOptionalAge() {
            return optionalAge;
        }

        public void setOptionalAge(Optional<Integer> optionalAge) {
            this.optionalAge = optionalAge;
        }
    }

}

其结果如下:

image.png

然后我们再验证一下反序列化

@Test
public void testDeserializeOptionalField() throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new Jdk8Module());

    String jsonString = "{"name":"Alice","optionalAge":25}";
    OptionalField optionalField = mapper.readValue(jsonString, OptionalField.class);
    System.out.println(optionalField.getName());
    System.out.println(optionalField.getOptionalAge().get());
}

结果如下

image.png

至此,已经知道如何实现序列化和反序列化Optional类型的字段了。