问题
By default, ThreeTenABP.LocalDateTime is converted to
{"date":{"day":10,"month":4,"year":2018},"time":{"hour":3,"minute":34,"nano":115000000,"second":18}}
I can write an adapter to support ISO date string 2018-04-10T03:45:26.009
class LocalDateTimeAdapter {
@ToJson
fun toJson(value: LocalDateTime): String {
return FORMATTER.format(value)
}
@FromJson
fun fromJson(value: String): LocalDateTime {
return FORMATTER.parse(value, LocalDateTime.FROM)
}
companion object {
private val FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME
}
}
How can I write an adapter which can support both format (fromJson)
{"date":{"day":10,"month":4,"year":2018},"time":{"hour":3,"minute":34,"nano":115000000,"second":18}}
2018-04-10T03:45:26.009
Beside identifying which the format is used in fromJson
, I am curious how Moshi internally perform toJson/fromJson for LocalDateTime
回答1:
You’ll need to use JsonReader.peek()
to determine the format of the incoming JSON, and then take action accordingly.
First install an adapter that converts LocalDateTime
to a string. That adapter should use a qualifier annotation.
@Retention(RetentionPolicy.RUNTIME)
@JsonQualifier
@interface DateString {
}
Next create the string adapter. It should be straightforward, and might delegate to Moshi’s built-in Rfc3339DateJsonAdapter.
public final class LocalDateAsStringAdapter {
@ToJson String toJson(@DateString LocalDateTime localDateTime) {
...
}
@FromJson @DateString LocalDateTime fromJson(String string) {
...
}
}
Finally create an adapter that delegates either to Moshi’s built in adapter (that one will use {...}
) or to your string adapter. This one prefers the string format, but you can do what you like.
public final class MultipleFormatsDateAdapter {
@ToJson void toJson(JsonWriter writer, LocalDateTime value,
@DateString JsonAdapter<LocalDateTime> stringAdapter) throws IOException {
stringAdapter.toJson(writer, value);
}
@FromJson LocalDateTime fromJson(JsonReader reader, @DateString JsonAdapter<LocalDateTime> stringAdapter,
JsonAdapter<LocalDateTime> defaultAdapter) throws IOException {
if (reader.peek() == JsonReader.Token.STRING) {
return stringAdapter.fromJson(reader);
} else {
return defaultAdapter.fromJson(reader);
}
}
}
This works because Moshi lets you declare multiple JsonAdapter
arguments to the @ToJson
and @FromJson
methods, and these arguments may be annotated.
It also relies on the way this feature works if the types are the same. Here we’re making a JsonAdapter<LocalDateTime>
by delegating to another JsonAdapter<LocalDateTime>
. When the types are the same Moshi uses its nextAdapter()
feature for composition.
来源:https://stackoverflow.com/questions/49750743/moshi-localdatetime-adapter-with-multiple-format