From 9759f64fca3320891cef6ec57e24ec8aa4a58f55 Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Tue, 18 Apr 2023 20:45:34 +0200 Subject: [PATCH] Fix error handling for deserializers Signed-off-by: Jacob Laursen --- .../serialization/InstantDeserializer.java | 11 +++- .../serialization/LocalDateDeserializer.java | 7 ++- .../LocalDateTimeDeserializer.java | 7 ++- .../InstantDeserializerTest.java | 58 +++++++++++++++++++ .../LocalDateDeserializerTest.java | 56 ++++++++++++++++++ 5 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/api/serialization/InstantDeserializerTest.java create mode 100644 bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializerTest.java diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/InstantDeserializer.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/InstantDeserializer.java index 22c4ea66cbe3e..0591540f45233 100644 --- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/InstantDeserializer.java +++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/InstantDeserializer.java @@ -14,6 +14,7 @@ import java.lang.reflect.Type; import java.time.Instant; +import java.time.format.DateTimeParseException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -35,8 +36,12 @@ public class InstantDeserializer implements JsonDeserializer { public @Nullable Instant deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) throws JsonParseException { String content = element.getAsString(); - // When writing this, the format of the provided UTC strings lacks the trailing 'Z'. - // In case this would be fixed in the future, gracefully support both with and without this. - return Instant.parse(content.endsWith("Z") ? content : content + "Z"); + try { + // When writing this, the format of the provided UTC strings lacks the trailing 'Z'. + // In case this would be fixed in the future, gracefully support both with and without this. + return Instant.parse(content.endsWith("Z") ? content : content + "Z"); + } catch (DateTimeParseException e) { + throw new JsonParseException("Could not parse as Instant: " + content, e); + } } } diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializer.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializer.java index 5b51db3d30b82..76f0b1fafe2c4 100644 --- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializer.java +++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializer.java @@ -14,6 +14,7 @@ import java.lang.reflect.Type; import java.time.LocalDate; +import java.time.format.DateTimeParseException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -34,6 +35,10 @@ public class LocalDateDeserializer implements JsonDeserializer { @Override public @Nullable LocalDate deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) throws JsonParseException { - return LocalDate.parse(element.getAsString().substring(0, 10)); + try { + return LocalDate.parse(element.getAsString().substring(0, 10)); + } catch (DateTimeParseException e) { + throw new JsonParseException("Could not parse as LocalDate: " + element.getAsString(), e); + } } } diff --git a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateTimeDeserializer.java b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateTimeDeserializer.java index 47851c05e0df3..81b24587958e9 100644 --- a/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateTimeDeserializer.java +++ b/bundles/org.openhab.binding.energidataservice/src/main/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateTimeDeserializer.java @@ -14,6 +14,7 @@ import java.lang.reflect.Type; import java.time.LocalDateTime; +import java.time.format.DateTimeParseException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -34,6 +35,10 @@ public class LocalDateTimeDeserializer implements JsonDeserializer { + gson.fromJson("\"invalid\"", Instant.class); + }); + } + + @ParameterizedTest + @ValueSource(strings = { "\"2023-04-17T20:38:01Z\"", "\"2023-04-17T20:38:01\"" }) + void instantWhenValidShouldParse(String input) { + assertThat((@Nullable Instant) gson.fromJson(input, Instant.class), + is(equalTo(Instant.ofEpochSecond(1681763881)))); + } +} diff --git a/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializerTest.java b/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializerTest.java new file mode 100644 index 0000000000000..116a8a87a79d0 --- /dev/null +++ b/bundles/org.openhab.binding.energidataservice/src/test/java/org/openhab/binding/energidataservice/internal/api/serialization/LocalDateDeserializerTest.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energidataservice.internal.api.serialization; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.time.LocalDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; + +/** + * Tests for {@link LocalDateDeserializer}. + * + * @author Jacob Laursen - Initial contribution + */ +@NonNullByDefault +@ExtendWith(MockitoExtension.class) +public class LocalDateDeserializerTest { + + private final Gson gson = new GsonBuilder() + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer()).create(); + + @Test + void localDateTimeWhenInvalidShouldThrowJsonParseException() { + assertThrows(JsonParseException.class, () -> { + gson.fromJson("\"invalid\"", LocalDateTime.class); + }); + } + + @Test + void instantWhenValidShouldParse() { + assertThat((@Nullable LocalDateTime) gson.fromJson("\"2023-04-17T20:38:01\"", LocalDateTime.class), + is(equalTo(LocalDateTime.of(2023, 4, 17, 20, 38, 1, 0)))); + } +}