У меня есть проект весенней загрузки, использующий базу данных Azure Cosmos для nosql в качестве базы данных, используя артефакт CosmosRepository
из spring-cloud-azure-starter-data-cosmos
. Моя сущность выглядит так:
import java.time.LocalDateTime;
import org.springframework.data.annotation.Id;
import com.azure.spring.data.cosmos.core.mapping.Container;
import com.azure.spring.data.cosmos.core.mapping.GeneratedValue;
import lombok.Data;
@Data
@Container
public class Post {
@Id
@GeneratedValue
private String id;
private String author;
private String content;
private String imageUrl;
private LocalDateTime creationTime;
}
проблема в том, что при сохранении данных creationTime
по какой-то причине сохраняется как массив (пример: "creationTime": [2024, 6, 16, 16, 51, 25, 571970017]
), а не строка ISO, которая, как я ожидаю, будет использоваться по умолчанию. По-видимому, это создает проблемы при использовании метода репозитория для сортировки сообщений по времени (public List<Post> findAllByOrderByCreationTimeDesc();
). Есть ли способ указать, что LocalDateTime
будет храниться как строка ISO, не меняя creationTime
на String
и делая это вручную? Я пробовал комментировать creationTime
с помощью весеннего @DateTimeFormat
, но, похоже, безрезультатно.
@ArchitectJamie Это числовой массив внутри самой Cosmos DB при запросе элементов контейнера.
Интересный. Можете ли вы опубликовать код, который используете для записи своего объекта в Cosmos? В большинстве случаев Java неявно вызывает toString()
для LocalDateTime, создавая строку ISO 8601, но может показаться, что сериализатор не делает этого.
@ArchitectJamie Я использую CosmosRepository
и его метод save()
, без специального кода
Я проверил исходный код SDK и увидел, что Джексон используется для сериализации в JSON. Я опубликовал ответ для вас. Надеюсь, это сработает. Дайте мне знать, если он нуждается в доработке.
Spring Data Azure Cosmos DB использует Джексона для сериализации объектов в формате Json. Это поведение Джексона по умолчанию, которое приводит к тому, что даты сохраняются в виде числовых массивов.
Джексон поддерживает ряд различных аннотаций, которые позволяют ему узнать, как следует сериализовать ввод и форматировать вывод.
Вы можете использовать аннотацию @JsonFormat
в классе модели, указав рекомендуемый формат ISO 8601 для Azure Cosmos DB.
@Data
@Container
public class Post {
@Id
@GeneratedValue
private String id;
private String author;
private String content;
private String imageUrl;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.fffffff'Z'")
private LocalDateTime creationTime;
}
Если вы предпочитаете переопределить поведение Джексона по умолчанию в области приложения, вы можете сделать это в своем файле application.properties
или application.yml
.
# Serialize dates as ISO 8601 strings
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.date-format=yyyy-MM-dd'T'HH:mm:ss.fffffff'Z'
Вариант первый работает, спасибо. Не уверен насчет второго, поскольку сериализация дат в виде строк уже кажется значением по умолчанию для Spring (при проверке запросов REST), я предполагаю, что пакет Azure имеет где-то отдельную конфигурацию для Джексона.
@Overdrowsed Скорее всего, ты прав. Почему они сделали это, если это означает, что вы не можете использовать встроенные функции даты Cosmos, остается загадкой.
@Overdrowsed Я копнул немного глубже и обнаружил, что есть специальные условия для правильного форматирования объектов ZonedDateTime
, но не LocalDateTime
. Я думаю, вместо этого вы могли бы использовать зонирование, поскольку информация о зонировании удалена из формата, но это похоже на недосмотр со стороны разработчиков.
На данный момент @JsonFormat
работает достаточно хорошо, я могу заменить на ZonedDateTime
или, возможно, в будущем создать проблему на github, спасибо за вашу помощь
Где вы видите числовой массив? В Cosmos DB или с помощью отладчика/инспектора? Пробовали ли вы получить эти данные обратно из Cosmos и распечатать их значение? Казалось бы, в рамках существует проблема с сериализацией, но я просто хотел проверить, не видите ли вы это только в инспекторе?