Moshi LocalDateTime adapter with multiple format

别来无恙 提交于 2020-06-24 22:28:39

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!