亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 objectMapper 將 JSON 日期格式反序列化為 ZonedDateTime

使用 objectMapper 將 JSON 日期格式反序列化為 ZonedDateTime

紅顏莎娜 2023-04-13 17:19:58
背景我有以下 JSON(來自 Kafka 的消息){      "markdownPercentage": 20,      "currency": "SEK",      "startDate": "2019-07-25"}我有以下(生成的 JSON 模式)POJO(我無法更改 POJO,因為它是公司的共享資源)public class Markdown {    @JsonProperty("markdownPercentage")    @NotNull    private Integer markdownPercentage = 0;    @JsonProperty("currency")    @NotNull    private String currency = "";    @JsonFormat(        shape = Shape.STRING,        pattern = "yyyy-MM-dd"    )    @JsonProperty("startDate")    @NotNull    private ZonedDateTime startDate;    // Constructors, Getters, Setters etc.}我們的應用程序是一個 Spring Boot 應用程序,它使用 Spring Cloud Stream 從 Kafka 讀取 JSON 消息 (1) 并使用 POJO (2) 然后對其進行處理。問題當應用程序嘗試將消息反序列化為對象時,它會拋出異常當前代碼我定義了以下 objectMapper/**     * Date mapper.     *     * @return the {@link ObjectMapper}     */    @Bean    public ObjectMapper objectMapper() {        ObjectMapper mapper = new ObjectMapper();        mapper.registerModule(new JavaTimeModule());        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));        return mapper;    }問題我知道 POJO 中生成的 ZonedDateTime 需要源消息中不存在的“時間”元素。我只能控制 objectMapper。是否有任何可能的配置可以使這項工作?筆記如果反序列化 POJO 中的時間元素“假定”為 startOfDay,即“00.00.00.000Z”,我很好
查看完整描述

5 回答

?
交互式愛情

TA貢獻1712條經驗 獲得超3個贊

我只能控制ObjectMapper. 是否有任何可能的配置可以使這項工作?


只要您對時間和時區的默認值感到滿意,就可以使用自定義反序列化器解決它:


public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {


    @Override

    public ZonedDateTime deserialize(JsonParser jsonParser,

                                     DeserializationContext deserializationContext)

                                     throws IOException {


        LocalDate localDate = LocalDate.parse(

                jsonParser.getText(), 

                DateTimeFormatter.ISO_LOCAL_DATE);


        return localDate.atStartOfDay(ZoneOffset.UTC);

    }

}

然后將其添加到模塊并將模塊注冊到您的ObjectMapper實例:


SimpleModule module = new SimpleModule();

module.addDeserializer(ZonedDateTime.class, new ZonedDateTimeDeserializer());


ObjectMapper mapper = new ObjectMapper();

mapper.registerModule(module);

如果將反序列化器添加到模塊中不適合您(從某種意義上說,此配置將應用于其他ZonedDateTime實例),那么您可以依靠混合來定義反序列化器將應用于哪些字段。首先定義一個mix-in接口,如下圖:


public interface MarkdownMixIn {


    @JsonDeserialize(using = ZonedDateTimeDeserializer.class)

    ZonedDateTime getDate();

}

然后將混合接口綁定到所需的類:


ObjectMapper mapper = new ObjectMapper();

mapper.addMixIn(Markdown.class, MarkdownMixIn.class);


查看完整回答
反對 回復 2023-04-13
?
長風秋雁

TA貢獻1757條經驗 獲得超7個贊

問題:我想將日期從 json 解析為 java LocalDateTime/ZonedDateTime 對象。ZonedDateTimeSerializer 存在但 ZonedDateTimeDeserializer 不存在。因此,為什么我創建了一個自定義 ZonedDateTimeDeserializer。


? public static final String ZONED_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSz";?


? @Getter

? @Setter

? @JsonSerialize(using = ZonedDateTimeSerializer.class)

? @JsonDeserialize(using = ZonedDateTimeDeserializer.class) // Doesn't exist, So I created a custom ZonedDateDeserializer utility class.

? @JsonFormat(pattern = ZONED_DATE_TIME_FORMAT)

? @JsonProperty("lastUpdated")

? private ZonedDateTime lastUpdated;

解決方案:我最終得到了更簡單、更少的代碼行。


用于反序列化ZonedDateTime的實用程序類:


/**

?* Custom {@link ZonedDateTime} deserializer.

?*

?* @param jsonParser? ? ? ? ? ? ?for extracting the date in {@link String} format.

?* @param deserializationContext for the process of deserialization a single root-level value.

?* @return {@link ZonedDateTime} object of the date.

?* @throws IOException throws I/O exceptions.

?*/

public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {


? ? @Override

? ? public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)

? ? ? ? ? ? throws IOException {


? ? ? ? return ZonedDateTime.parse(jsonParser.getText(), DateTimeFormatter.ofPattern(ZONED_DATE_TIME_FORMAT));

? ? }

}

如果您改用LocalDateTime怎么辦。在那種情況下,它甚至更容易,反序列化器和序列化器類都已經提供給我們了。不需要上面定義的自定義實用程序類:


? @Getter

? @Setter

? @JsonSerialize(using = LocalDateSerializer.class)

? @JsonDeserialize(using = LocalDateTimeDeserializer.class)

? @JsonFormat(pattern = ZONED_DATE_TIME_FORMAT) //Specify the format you want: "yyyy-MM-dd'T'HH:mm:ss.SSS"

? @JsonProperty("created")

? private LocalDateTime created;

關鍵詞:json格式 localDateTime zonedDateTime


查看完整回答
反對 回復 2023-04-13
?
Qyouu

TA貢獻1786條經驗 獲得超11個贊

不幸的是,默認情況下您不能反序列化為String Object格式ZonedDateTime。但是您可以通過兩種方式克服這個問題。


方式01


ZonedDateTime將類型更改為LocalDate在您的類中鍵入POJO并將值作為字符串傳遞03-06-2012


方式02


但是如果您必須使用時區存儲日期和時間,那么您必須執行以下方法來克服


步驟01


ZonedDateTime使用 DateTimeFormat創建反序列化類


public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {


    @Override

    public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {


        DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss z");

        LocalDate localDate = LocalDate.parse(p.getText(),dateTimeFormatter);


        return localDate.atStartOfDay(ZoneOffset.UTC);

    }

}

步驟02


@JsonDeserialize在方法級別注釋的支持下,您必須在 POJO 類中將反序列化類與受影響的字段一起使用。


@JsonDeserialize(using = ZonedDateTimeDeserializer.class)

private ZonedDateTime startDate;

步驟03


以 ZonedDateTimeDeserializer 類給出的上述格式將值作為字符串傳遞


       "startDate" : "09-03-2003 10:15:00 Europe/Paris"


查看完整回答
反對 回復 2023-04-13
?
梵蒂岡之花

TA貢獻1900條經驗 獲得超5個贊

遺憾的是,如果不將 POJO 的類型更改為 LocalDate,那將很困難。

我能想到的最接近的解決方案是為杰克遜寫一個習慣JsonDeserializer,這絕對不是那種事情的好習慣。


查看完整回答
反對 回復 2023-04-13
?
HUX布斯

TA貢獻1876條經驗 獲得超6個贊

您可以編寫自己的反序列化器,如@cassiomolin答案中所示。但也有另一種選擇。在堆棧跟蹤中,我們有DeserializationContext.weirdStringException方法允許我們提供DeserializationProblemHandler處理奇怪字符串值的方法。請參閱以下示例:


import com.fasterxml.jackson.annotation.JsonFormat;

import com.fasterxml.jackson.annotation.JsonFormat.Shape;

import com.fasterxml.jackson.annotation.JsonProperty;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;

import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.IOException;

import java.time.LocalDate;

import java.time.ZonedDateTime;

import java.time.format.DateTimeFormatter;

import java.util.TimeZone;


public class AppJson {


    public static void main(String[] args) throws IOException {

        ObjectMapper mapper = new ObjectMapper();

        // override default time zone if needed

        mapper.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));


        mapper.registerModule(new JavaTimeModule());

        mapper.addHandler(new DeserializationProblemHandler() {

            @Override

            public Object handleWeirdStringValue(DeserializationContext ctxt, Class<?> targetType,

                String valueToConvert, String failureMsg) {

                LocalDate date = LocalDate.parse(valueToConvert, DateTimeFormatter.ISO_DATE);

                return date.atStartOfDay(ctxt.getTimeZone().toZoneId());

            }

        });

        String json = "{\"startDate\": \"2019-07-25\"}";

        Markdown markdown = mapper.readValue(json, Markdown.class);

        System.out.println(markdown);

    }

}

上面的代碼打?。?/p>


Markdown{startDate=2019-07-25T00:00-07:00[America/Los_Angeles]}


查看完整回答
反對 回復 2023-04-13
  • 5 回答
  • 0 關注
  • 362 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號