自定义JackSon日期解析器CustomDateDeseralizer

x33g5p2x  于2022-09-17 转载在 Java  
字(3.6k)|赞(0)|评价(0)|浏览(426)

了解如何在使用 jackson解析json 时反序列化多种日期格式。

详细视频笔记

Jackson handles serialization and deserialization of dates 默认使用 GMT,格林威治标准时间(时区缩写),用于所有日期处理,除非另有配置。如果您公开多个客户端发布到的休息服务,您可能希望灵活地支持多种日期格式。让我们通过编写自定义日期反序列化器来了解如何处理各种日期格式。

项目设置

我们使用 simple archetype quick start 和导入的依赖项 jackson 和 apache commons lang 创建了一个 maven 项目。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

创建反序列化器

回顾一下,序列化和反序列化是与 json 相互转换的过程。例如,您可能有想要使用jackson将其转换为数组列表的 json 数组。或者您可以使用 gson 执行相同的转换。当用户发布到服务或我们通过读取文件来使用 json 时,我们将获取 json 并将其转换为 java 对象。读取日期时,我们希望将其解析为日期而不是字符串。

为此,我们将通过扩展 UntypedObjectDeserializer 创建一个自定义jackson解析器,如果需要绑定未知类型的内容,则使用解析器实现。我们将首先检查令牌是否为字符串,以及是否使用 apache commons 解析以多种格式传递的日期。如果抛出异常,我们将只使用上下文进行解析。

class CustomDateDeseralizer extends UntypedObjectDeserializer {

    private static final long serialVersionUID = -2275951539867772400L;

    @Override
    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {

        if (jp.getCurrentTokenId() == JsonTokenId.ID_STRING) {
            try {
                return DateUtils.parseDate(jp.getText(), new String[] {
                        "MM/dd/yyyy", "yyyy.MM.dd G 'at' HH:mm:ss z" });
            } catch (Exception e) {
                return super.deserialize(jp, ctxt);
            }
        } else {
            return super.deserialize(jp, ctxt);
        }
    }
}

将反序列化器注册为 SimpleModule

注册反序列化器后,我们必须指示 ObjectMapper。在 Jackson 1.7 中,引入了模块来扩展 jackson 功能,因此我们可以创建 SimpleModule 并注册我们的 CustomDateDeseralizer 类。

private ObjectMapper configureObjectMapper() {

    ObjectMapper objectMapper = new ObjectMapper();

    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addDeserializer(Object.class, new CustomDateDeseralizer());
    objectMapper.registerModule(simpleModule);

    return objectMapper;
}

使用 Spring Boot 注册 ObjectMapper

如果您使用的是 spring boot,它会自动为您配置一个 ObjectMapper。要覆盖默认配置,只需创建一个名为 objectMapper 的 bean 并提供您的配置。它可能看起来像这样:

@Bean
public ObjectMapper objectMapper() {

    ObjectMapper objectMapper = new ObjectMapper();

    // register your module

    return objectMapper;
}

把它放在一起

创建一个带有字符串和两个日期的示例 json,我们将希望通过 ObjectMapper 运行它并验证它是否创建了 java.util.date 对象。在调用 objectMapper.readValue 时,我们将指定将 json 键和值放到 HashMap 中。然后遍历key,将输出键、值和值类类型。

JSON示例

{
    "name": "Justin Musgrove",
    "shortDateFormat": "03/05/2015",
    "longDateFormat": "2001.07.04 AD at 12:08:56 PDT"
}

程序

String objectAsJson = "{\"name\": \"Justin Musgrove\", \"shortDateFormat\": \"03/05/2015\",\"longDateFormat\": \"2001.07.04 AD at 12:08:56 PDT\"}";

@Test
public void deserializeDates() throws JsonParseException,
        JsonMappingException, IOException {

    ObjectMapper objectMapper = configureObjectMapper();

    @SuppressWarnings("unchecked")
    Map<Object, Object> jsonAsMap = objectMapper.readValue(objectAsJson,
            HashMap.class);

    for (Entry<Object, Object> entry : jsonAsMap.entrySet()) {
        System.out.println(entry.getKey());
        System.out.println(entry.getValue());
        System.out.println(entry.getValue().getClass());
        System.out.println("----");
    }
}

输出

name
Justin Musgrove
class java.lang.String
----
shortDateFormat
Thu Mar 05 00:00:00 CST 2015
class java.util.Date
----
longDateFormat
Wed Jul 04 14:08:56 CDT 2001
class java.util.Date
----

感谢阅读,祝您幸福每一天!

相关文章