Skip to content

Commit

Permalink
Merge pull request #246 from mercadopago/fix/parse-iso8601-dates
Browse files Browse the repository at this point in the history
Refactor Gson OffsetDatetime adapter in Serializer
  • Loading branch information
romerosilva-meli authored Nov 17, 2022
2 parents f11197f + 1246057 commit ed5b017
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 8 deletions.
36 changes: 29 additions & 7 deletions src/main/java/com/mercadopago/serialization/Serializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
Expand All @@ -24,26 +25,47 @@
import java.lang.reflect.Type;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

/** Serializer class, responsible for objects serialization and deserialization. */
public class Serializer {

private static final String DESERIALIZE_DATE_FORMAT_ISO8601 =
"yyyy-MM-dd'T'HH:mm:ss[.SSS][XXX][XX][X]";
private static final DateTimeFormatter DESERIALIZE_DATE_FORMAT_ISO8601_EXTENDED =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS][XXX][XX][X]");

private static final DateTimeFormatter DESERIALIZE_DATE_FORMAT_ISO8601_BASIC =
DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss[.SSS][XXX][XX][X]");

private static final DateTimeFormatter[] ISO8601_DATETIME_FORMATTERS =
new DateTimeFormatter[] {
DateTimeFormatter.ISO_DATE_TIME,
DESERIALIZE_DATE_FORMAT_ISO8601_EXTENDED,
DESERIALIZE_DATE_FORMAT_ISO8601_BASIC,
};

private static final String SERIALIZE_DATE_FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

private static OffsetDateTime parseDateTime(JsonElement json) {
for (int i = 0; i < ISO8601_DATETIME_FORMATTERS.length; i++) {
try {
return OffsetDateTime.parse(json.getAsString(), ISO8601_DATETIME_FORMATTERS[i]);
} catch (DateTimeParseException e) {
// try all formatters, if none works, throw exception from last one
if (i == ISO8601_DATETIME_FORMATTERS.length - 1) {
throw e;
}
}
}
return null;
}

private static final Gson GSON =
new GsonBuilder()
.registerTypeAdapter(
OffsetDateTime.class,
(JsonDeserializer<OffsetDateTime>)
(json, type, context) ->
OffsetDateTime.parse(
json.getAsString(),
DateTimeFormatter.ofPattern(DESERIALIZE_DATE_FORMAT_ISO8601)))
(JsonDeserializer<OffsetDateTime>) (json, type, context) -> parseDateTime(json))
.registerTypeAdapter(
OffsetDateTime.class,
(JsonSerializer<OffsetDateTime>)
Expand Down
10 changes: 9 additions & 1 deletion src/test/java/com/mercadopago/helper/MockHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,15 @@ public static String readResponseFile(String mockFile) throws IOException {
return readFile(mockFile, MOCKS_RESPONSE_PATH);
}

private static String readFile(String mockFile, String path) throws IOException {
/**
* Read file contents and convert them to string.
*
* @param mockFile the mock file to be read
* @param path path to file
* @return string contents of file
* @throws IOException problem reading file
*/
public static String readFile(String mockFile, String path) throws IOException {

File file = new File(StringUtils.join(path, mockFile));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"timestamps": [
"2021-01-13T17:06:29.595034354Z",
"2021-01-13T17:06:29.595034354-04:00",
"2021-02-14T08:52:52.000Z",
"2021-02-14T08:52:52.000-04:00",
"2021-04-16T03:03:03.3Z",
"2021-04-16T03:03:03Z",
"20210517T040404Z",
"20210517T040404-03:00"
]
}
21 changes: 21 additions & 0 deletions src/test/java/com/mercadopago/serialization/SerializerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
import com.mercadopago.exceptions.MPJsonParseException;
import com.mercadopago.helper.MockHelper;
import com.mercadopago.net.MPElementsResourcesPage;
import com.mercadopago.net.MPResource;
import com.mercadopago.net.MPResourceList;
import com.mercadopago.net.MPResultsResourcesPage;
import com.mercadopago.resources.customer.CustomerCard;
import com.mercadopago.resources.merchantorder.MerchantOrder;
import com.mercadopago.resources.payment.Payment;
import java.io.IOException;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -122,4 +125,22 @@ public void serializeToJsonSuccess() {

assertNotNull(json);
}

@Test
public void deserializeListFromJsonIso8601Timestamps() throws IOException, MPJsonParseException {
String timestampsJson =
MockHelper.readFile(
"serializer_iso8601_timestamps.json",
"./src/test/java/com/mercadopago/resources/mocks/helper/");
Iso8601Timestamps deserialized =
Serializer.deserializeFromJson(Iso8601Timestamps.class, timestampsJson);

assertEquals(2021, deserialized.timestamps.get(0).getYear());
assertEquals(1, deserialized.timestamps.get(0).getMonth().getValue());
assertEquals(13, deserialized.timestamps.get(0).getDayOfYear());
}

private static class Iso8601Timestamps extends MPResource {
public List<OffsetDateTime> timestamps;
}
}

0 comments on commit ed5b017

Please sign in to comment.