Moshi is a library for marshalling/unmarshalling JSON. The Moshi API is very similar to the API of its predecessor Gson. Just like Gson, Moshi does not have support for LocalDate(Time) processing. This is the recommended Java Date/Time representation, so Moshi does not work out of the box for Java, and that's a shame.
Here's how you can solve this, for LocalDateTime. The procedure for LocalDate is similar.
Option 1: write an Adapter from scratch
1. Write the Adapter class
public class LocalDateTimeAdapter {
// Specify in which format you want your DateTime
private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
@ToJson
public String toText(LocalDateTime dateTime) {
return dateTime.format(formatter);
}
@FromJson
public LocalDateTime fromText(String text) {
return LocalDateTime.parse(text, formatter);
}
}
2. Add the adapter when building Moshi
Moshi moshi = new Moshi.Builder()
.add(new LocalDateTimeAdapter())
.build();
// That's all!
// Now just parse (or serialise) your data as normal
// Here serialising a Ticket object
JsonAdapter<Ticket> jsonAdapter = moshi.adapter( Ticket.class);
System.out.println(jsonAdapter.indent(" ").toJson(ticket));
Option 2: write an Adapter that delegates to Moshi's Date adapter
Here we are using the Moshi
Rfc3339DateJsonAdapter, that is in the Moshi adapter's library. It can marshall/unmarshall
java.util.Date.
1. Add the Moshi adapters library
I'm using gradle and add the dependency to build.gradle.kt, in addition to the moshi library that was already theredependencies {
implementation("com.squareup.moshi:moshi:1.15.0")
implementation("com.squareup.moshi:moshi-adapters:1.15.0")
//...
}
2. Write the Adapter class
In the adapter I'm converting LocalDateTime to/from Date and then use the Moshi adapter to convert the Date to/from JSON.
//...
// Do NOT import this from com.squareup.moshi.Rfc3339DateJsonAdapter, that one's deprecated
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter;
public class DelegatingLocalDateTimeAdapter {
// adding .nullSafe() to the adapter allows it to write null dates in json rather than skipping them
private static final JsonAdapter<Date> ADAPTER = new Rfc3339DateJsonAdapter().nullSafe();
@ToJson
public String toJson(LocalDateTime timestamp) {
return ADAPTER.toJson(Date.from(timestamp.atZone(ZoneId.systemDefault()).toInstant()));
}
@FromJson
public LocalDateTime fromJson(String json) throws IOException {
return LocalDateTime.ofInstant( ADAPTER.fromJson(json).toInstant(), ZoneId.systemDefault());
}
}
3. Add the adapter when building Moshi
This step is the same as the last step in Option 1
Moshi moshi = new Moshi.Builder()
.add(new DelegatingLocalDateTimeAdapter())
.build();
// That's all!
// Now just parse (or serialise) your data as normal
// Here serialising a Ticket object
JsonAdapter<Ticket> jsonAdapter = moshi.adapter( Ticket.class);
System.out.println(jsonAdapter.indent(" ").toJson(ticket));