Jackson LocalDate: один выходной во время сериализации - PullRequest
0 голосов
/ 11 декабря 2018

У меня возникают проблемы, когда Джексон пытается сериализовать столбцы LocalDate из моих классов, но с базой данных все в порядке, каждый раз, когда JSON отображает один выходной из базы данных.

В то время как база данных отображается так, как задумано:

2018-10-01

Вывод JSON при вызове точки входа Spring REST:

{ "ticketStart": "2018-09-30" }

Показывает, что день был потерян.Таблица базы данных не хранит время, а только дату, как и предполагалось. Часовые пояса полностью отбрасываются, поскольку мой проект предназначен для внутреннего использования.Я пытался отыскать свою конкретную проблему в Google, и единственное, что я нашел это и это , но ни один из них не решил мою проблему.

Существует способ принудительно выполнить сериализациюдаты из моей базы данных, как есть, (иначе: преобразование отключено).

Код объекта:

@Entity
@Table(name="tickets")
public class Ticket
{
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Getter
  @Setter
  private long TicketId;

  @Column(unique=true)
  @Getter
  @Setter
  private LocalDate TicketStart;

  @Column(unique=true)
  @Getter
  @Setter
  private LocalDate TicketEnd;

  //.... some fields omitted
}

Поскольку объект «Билеты» генерируется автоматически сценарием CRON или указывается в диапазонедаты, когда билет имеет понедельник и воскресенье каждой недели:

public Ticket GenerateEmptyTicket(LocalDate begin, LocalDate end)
{
    Ticket newTicket = new Ticket();

    newTicket.setTicketStart(begin);
    newTicket.setTicketEnd(end);
    newTicket.setYear(begin.getYear());
    newTicket.setMonth(begin.getMonth());
    newTicket.setLastMod(new Date());

    boolean isLocked = false;
    LocalDate date = LocalDate.now();
    if(date.isAfter(end)) isLocked = true;

    newTicket.setLocked(isLocked);

    //@TODO: Set a default responsible in the configuration.
    SystemUser rootUser = usersRepo.findByUsername("root").get();
    newTicket.setResponsable(rootUser);

    return newTicket;
}

public void GenerateTicketsBetweenTwoDates(LocalDate begin, LocalDate end)
{        
    List<LocalDate> weekDates = new ArrayList<>();

    if(begin.getDayOfWeek() != DayOfWeek.MONDAY)
        while(begin.getDayOfWeek()  != DayOfWeek.MONDAY)
            begin = begin.minusDays(1);


    LocalDate tmp = begin;
    while(tmp.isBefore(end)){
        weekDates.add(tmp);
        tmp = tmp.plusWeeks(1);
    }

    if(end.getDayOfWeek() == DayOfWeek.MONDAY)
        weekDates.add(end);


    LocalDate current = LocalDate.now();
    List<Ticket> ticketsToSave = new ArrayList<>();

    for(LocalDate dat : weekDates)
    {
        logger.info("BEGIN DATE:" + dat.toString());
        LocalDate __end = dat.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        if(current.isAfter(__end)) logger.info("LOCKED: YES");

        ticketsToSave.add(GenerateEmptyTicket(dat, __end));
    }

    ticketsRepo.saveAll(ticketsToSave);
}    

В базе данных и сериализации Джексона нет ошибок, только нежелательный результат "выходного дня" в результате сериализации.

ПРИМЕЧАНИЕ. Соединение JDBC базы данных (MySQL) указывает useJDBCCompliantTimezoneShift=false&useLegacyDatetimeCode=false&serverTimezone=UTC из application.properties spring.datasource.url

1 Ответ

0 голосов
/ 06 января 2019

Проблема с часовым поясом

Столько всего получается, Spring извлекает даты из базы данных, и я предполагаю, что она использует java.util.Date (который учитывает часовой пояс системы), чтобы сначала проанализировать его, а затем преобразовать в java.time.LocalDate,использование TimeZone.setDefault(TimeZone.getTimeZone("UTC")); полностью решит проблему, используя это так:

@SpringBootApplication
public class MyTicketApplication {

    public static void main(String[] args) {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        SpringApplication.run(MyTicketApplication.class, args);
    }
}
...