Skip to content

Commit

Permalink
Merge pull request #4 from GoodforGod/dev
Browse files Browse the repository at this point in the history
[1.1.0
  • Loading branch information
GoodforGod authored Nov 19, 2021
2 parents 084b99f + def69e4 commit df21b9a
Show file tree
Hide file tree
Showing 55 changed files with 1,229 additions and 256 deletions.
53 changes: 36 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Gson configuration and serializers/deserializers for Date/Time in [java.time.*](
**Gradle**
```groovy
dependencies {
implementation "io.goodforgod:gson-configuration:1.0.0"
implementation "io.goodforgod:gson-configuration:1.1.0"
}
```

Expand All @@ -21,36 +21,53 @@ dependencies {
<dependency>
<groupId>io.goodforgod</groupId>
<artifactId>gson-configuration</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
</dependency>
```

## Serializers\Deserializers

Library include serializers & deserializers for most [java.time.*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html)
datetime objects, supported list:
- Instant
- LocalDate
- LocalTime
- LocalDateTime
- Instant
- OffsetTime
- OffsetDateTime
- ZonedDateTime
- DayOfWeek
- Month
- Year
- YearMonth
- Month
- MonthDay
- DayOfWeek
- ZoneId
- ZoneOffset

All adapters register with **ISO8601** formatters by defaults, but you can register them manually with your formatter.

## Formats

Gson Configuration by default comes with [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) with millis precision for all APIs:

Here is list of default formatters for all *java.time.** APIs:
- LocalDateTime - *uuuu-MM-dd'T'HH:mm:ss[.SSS]*
- LocalDate - *uuuu-MM-dd*
- LocalTime - *HH:mm:ss[.SSS]*
- OffsetDateTime - *uuuu-MM-dd'T'HH:mm:ss[.SSS]XXX*
- OffsetTime - *HH:mm:ss[.SSS]XXX*
- ZonedDateTime - *uuuu-MM-dd'T'HH:mm:ss[.SSS]XXX[VV]*

If you want to know more about Java Date & Time formats, you can [read more here](https://goodforgod.dev/posts/2/)

## Gson Configuration

Library provides configuration for configuring *GsonBuilder* for most properties:

```java
final GsonBuilder builder = new GsonConfiguration()
.setDateFormat(GsonConfiguration.ISO_8601_FORMATTER)
.setInstantFormat("yyyy-MM-dd HH:mm:ss")
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
.setInstantFormat("uuuu-MM-dd HH:mm:ss")
.setComplexMapKeySerialization(true)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
Expand All @@ -66,7 +83,7 @@ final GsonBuilder builder = new GsonConfiguration()
You can configure DateTimeFormatters for provided adapters:
```java
final GsonBuilder builder = new GsonConfiguration()
.setInstantFormat("yyyy-MM-dd HH:mm:ss")
.setInstantFormat("uuuu-MM-dd HH:mm:ss")
.builder();
```

Expand All @@ -85,14 +102,16 @@ final GsonConfiguration configuration = GsonConfiguration.ofProperties(propertie

Full list of properties ([check GsonProperties](https://github.com/GoodforGod/gson-configuration/blob/master/src/main/java/io/gson/adapters/config/GsonProperties.java)):
```properties
gson.format.instant=yyyy-MM-dd'T'HH:mm:ssX
gson.format.localDate=yyyy-MM-dd
gson.format.localTime=HH:mm:ss
gson.format.localDateTime=yyyy-MM-dd'T'HH:mm:ss
gson.format.instant=uuuu-MM-dd'T'HH:mm:ssX
gson.format.localDate=uuuu-MM-dd
gson.format.localTime=HH:mm:ss.SSS
gson.format.localDateTime=uuuu-MM-dd'T'HH:mm:ss.SSS
gson.format.offsetTime=HH:mm:ss.SSSXXX
gson.format.offsetDateTime=yyyy-MM-dd'T'HH:mm:ss.SSSXXX
gson.format.zonedDateTime=yyyy-MM-dd'T'HH:mm:ss.SSSXXX[VV]
gson.format.year=yyyy
gson.format.offsetDateTime=uuuu-MM-dd'T'HH:mm:ss.SSSXXX
gson.format.zonedDateTime=uuuu-MM-dd'T'HH:mm:ss.SSSXXX
gson.format.year=uuuu
gson.format.yearMonth=uuuu-MM
gson.format.monthDay=MM-dd
gson.format.date=yyyy-MM-dd'T'HH:mm:ss.SSSXXX

gson.lenient=true
Expand Down Expand Up @@ -130,13 +149,13 @@ GsonBuilder builder = GsonAdapters.builder();
You can register them manually:
```java
GsonBuilder builder = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
```

You can register with custom formatter also:
```java
GsonBuilder builder = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new LocalDateAdapter(DateTimeFormatter.ISO_LOCAL_DATE))
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer(DateTimeFormatters.ISO_LOCAL_DATE))
```

## License
Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ sonarqube {
}

dependencies {
implementation "com.google.code.gson:gson:2.8.8"
api "com.google.code.gson:gson:2.8.9"

testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.8.1"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.8.1"
testImplementation "org.junit.jupiter:junit-jupiter-params:5.8.1"
}

test {
failFast(true)
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
groupId=io.goodforgod
artifactId=gson-configuration
artifactVersion=1.0.0
artifactVersion=1.1.0


##### GRADLE #####
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
133 changes: 133 additions & 0 deletions src/main/java/io/goodforgod/gson/configuration/DateTimeFormatters.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package io.goodforgod.gson.configuration;

import static java.time.temporal.ChronoField.*;

import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;

/**
* ISO8601 formats and patterns
*
* @author Anton Kurako (GoodforGod)
* @since 05.11.2021
*/
public final class DateTimeFormatters {

private DateTimeFormatters() {}

/**
* uuuu
*/
public static final DateTimeFormatter ISO_YEAR = new DateTimeFormatterBuilder()
.appendValue(YEAR, 4, 4, SignStyle.EXCEEDS_PAD)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* uuuu-MM
*/
public static final DateTimeFormatter ISO_YEAR_MONTH = new DateTimeFormatterBuilder()
.append(ISO_YEAR)
.appendLiteral('-')
.appendValue(MONTH_OF_YEAR, 2)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* MM-dd
*/
public static final DateTimeFormatter ISO_MONTH_DAY = new DateTimeFormatterBuilder()
.appendValue(MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH, 2)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* @see DateTimeFormatter#ISO_INSTANT
*/
public static final DateTimeFormatter ISO_INSTANT = DateTimeFormatter.ISO_INSTANT;

/**
* uuuu-MM-dd
*/
public static final DateTimeFormatter ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
.append(ISO_YEAR_MONTH)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH, 2)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* HH:mm:ss.SSS
*/
public static final DateTimeFormatter ISO_LOCAL_TIME = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 3, 3, true)
.optionalEnd()
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);

/**
* uuuu-MM-dd'T'HH:mm:ss.SSS
*/
public static final DateTimeFormatter ISO_LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_DATE)
.appendLiteral('T')
.append(ISO_LOCAL_TIME)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* HH:mm:ss.SSSXXX
*/
public static final DateTimeFormatter ISO_OFFSET_TIME = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_TIME)
.appendOffsetId()
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);

/**
* uuuu-MM-dd'T'HH:mm:ss.SSSXXX
*/
public static final DateTimeFormatter ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_DATE_TIME)
.appendOffsetId()
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* uuuu-MM-dd'T'HH:mm:ss.SSSXXX[VV]
*/
public static final DateTimeFormatter ISO_ZONED_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_OFFSET_DATE_TIME)
.optionalStart()
.appendLiteral('[')
.parseCaseSensitive()
.appendZoneRegionId()
.appendLiteral(']')
.optionalEnd()
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT)
.withChronology(IsoChronology.INSTANCE);

/**
* ISO8601 for {@link java.util.Date} and {@link java.sql.Timestamp}
*/
public static final String ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,65 @@ public final class GsonAdapterBuilder {

private GsonAdapterBuilder() {}

public static GsonBuilder builder() {
private static GsonBuilder getCommonBuilder() {
return new GsonBuilder()
.setDateFormat(GsonConfiguration.DATE_ISO_8601_PATTERN)
.registerTypeAdapter(DayOfWeek.class, new DayOfWeekDeserializer())
.registerTypeAdapter(DayOfWeek.class, new DayOfWeekSerializer())
.registerTypeAdapter(Month.class, new MonthDeserializer())
.registerTypeAdapter(Month.class, new MonthSerializer())
.registerTypeAdapter(Year.class, new YearDeserializer())
.registerTypeAdapter(Year.class, new YearSerializer())
.registerTypeAdapter(ZoneId.class, new ZoneIdDeserializer())
.registerTypeAdapter(ZoneId.class, new ZoneIdSerializer())
.registerTypeAdapter(Instant.class, new InstantDeserializer())
.registerTypeAdapter(Instant.class, new InstantSerializer())
.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer())
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
.registerTypeAdapter(LocalTime.class, new LocalTimeDeserializer())
.registerTypeAdapter(LocalTime.class, new LocalTimeSerializer())
.registerTypeAdapter(LocalDateTime.class, new LocalDateDeserializer())
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer())
.registerTypeAdapter(OffsetTime.class, new OffsetTimeDeserializer())
.registerTypeAdapter(OffsetTime.class, new OffsetTimeSerializer())
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeDeserializer())
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeSerializer())
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeDeserializer())
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer());
.setDateFormat(DateTimeFormatters.ISO_DATE)
.registerTypeAdapter(DayOfWeek.class, DayOfWeekDeserializer.INSTANCE)
.registerTypeAdapter(DayOfWeek.class, DayOfWeekSerializer.INSTANCE)
.registerTypeAdapter(Month.class, MonthDeserializer.INSTANCE)
.registerTypeAdapter(Month.class, MonthSerializer.INSTANCE)
.registerTypeAdapter(ZoneId.class, ZoneIdDeserializer.INSTANCE)
.registerTypeAdapter(ZoneId.class, ZoneIdSerializer.INSTANCE)
.registerTypeAdapter(ZoneOffset.class, ZoneOffsetDeserializer.INSTANCE)
.registerTypeAdapter(ZoneOffset.class, ZoneOffsetSerializer.INSTANCE);
}

public static GsonBuilder builder() {
return getCommonBuilder()
.registerTypeAdapter(Year.class, YearDeserializer.INSTANCE)
.registerTypeAdapter(Year.class, YearSerializer.INSTANCE)
.registerTypeAdapter(YearMonth.class, YearMonthDeserializer.INSTANCE)
.registerTypeAdapter(YearMonth.class, YearMonthSerializer.INSTANCE)
.registerTypeAdapter(MonthDay.class, MonthDayDeserializer.INSTANCE)
.registerTypeAdapter(MonthDay.class, MonthDaySerializer.INSTANCE)
.registerTypeAdapter(Instant.class, InstantDeserializer.INSTANCE)
.registerTypeAdapter(Instant.class, InstantSerializer.INSTANCE)
.registerTypeAdapter(LocalDate.class, LocalDateDeserializer.INSTANCE)
.registerTypeAdapter(LocalDate.class, LocalDateSerializer.INSTANCE)
.registerTypeAdapter(LocalTime.class, LocalTimeDeserializer.INSTANCE)
.registerTypeAdapter(LocalTime.class, LocalTimeSerializer.INSTANCE)
.registerTypeAdapter(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE)
.registerTypeAdapter(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
.registerTypeAdapter(OffsetTime.class, OffsetTimeDeserializer.INSTANCE)
.registerTypeAdapter(OffsetTime.class, OffsetTimeSerializer.INSTANCE)
.registerTypeAdapter(OffsetDateTime.class, OffsetDateTimeDeserializer.INSTANCE)
.registerTypeAdapter(OffsetDateTime.class, OffsetDateTimeSerializer.INSTANCE)
.registerTypeAdapter(ZonedDateTime.class, ZonedDateTimeDeserializer.INSTANCE)
.registerTypeAdapter(ZonedDateTime.class, ZonedDateTimeSerializer.INSTANCE);
}

public static GsonBuilder builder(GsonConfiguration configuration) {
return getCommonBuilder()
.setDateFormat(configuration.getDateFormat())
.registerTypeAdapter(Year.class, new YearDeserializer(configuration.getYearFormat()))
.registerTypeAdapter(Year.class, new YearSerializer(configuration.getYearFormat()))
.registerTypeAdapter(YearMonth.class, new YearMonthDeserializer(configuration.getYearMonthFormat()))
.registerTypeAdapter(YearMonth.class, new YearMonthSerializer(configuration.getYearMonthFormat()))
.registerTypeAdapter(MonthDay.class, new MonthDayDeserializer(configuration.getMonthDayFormat()))
.registerTypeAdapter(MonthDay.class, new MonthDaySerializer(configuration.getMonthDayFormat()))
.registerTypeAdapter(Instant.class, new InstantDeserializer(configuration.getInstantFormat()))
.registerTypeAdapter(Instant.class, new InstantSerializer(configuration.getInstantFormat()))
.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer(configuration.getLocalDateFormat()))
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer(configuration.getLocalDateFormat()))
.registerTypeAdapter(LocalTime.class, new LocalTimeDeserializer(configuration.getLocalTimeFormat()))
.registerTypeAdapter(LocalTime.class, new LocalTimeSerializer(configuration.getLocalTimeFormat()))
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer(configuration.getLocalDateTimeFormat()))
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer(configuration.getLocalDateTimeFormat()))
.registerTypeAdapter(OffsetTime.class, new OffsetTimeDeserializer(configuration.getOffsetTimeFormat()))
.registerTypeAdapter(OffsetTime.class, new OffsetTimeSerializer(configuration.getOffsetTimeFormat()))
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeDeserializer(configuration.getOffsetDateTimeFormat()))
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeSerializer(configuration.getOffsetDateTimeFormat()))
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeDeserializer(configuration.getZonedDateTimeFormat()))
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeSerializer(configuration.getZonedDateTimeFormat()));
}
}
Loading

0 comments on commit df21b9a

Please sign in to comment.