9

默认情况下,ThreeTenABP.LocalDateTime 转换为

{"date":{"day":10,"month":4,"year":2018},"time":{"hour":3,"minute":34,"nano":115000000,"second":18}}

我可以编写一个适配器来支持 ISO 日期字符串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
    }
}

如何编写一个可以同时支持两种格式的适配器(fromJson)

  • {"date":{"day":10,"month":4,"year":2018},"time":{"hour":3,"minute":34,"nano":115000000,"second":18}}
  • 2018-04-10T03:45:26.009

除了确定使用哪种格式之外fromJson,我很好奇 Moshi 如何在内部为 LocalDateTime 执行 toJson/fromJson

4

1 回答 1

11

您需要使用JsonReader.peek()来确定传入 JSON 的格式,然后采取相应措施。

首先安装一个转换LocalDateTime为字符串的适配器。该适配器应使用限定符注释。

@Retention(RetentionPolicy.RUNTIME)
@JsonQualifier
@interface DateString {
}

接下来创建字符串适配器。它应该很简单,并且可能委托给 Moshi 的内置 Rfc3339DateJsonAdapter。

public final class LocalDateAsStringAdapter {
  @ToJson String toJson(@DateString LocalDateTime localDateTime) {
    ...
  }

  @FromJson @DateString LocalDateTime fromJson(String string) {
    ...
  }
}

最后创建一个适配器,委托给 Moshi 的内置适配器(将使用{...})或您的字符串适配器。这个更喜欢字符串格式,但你可以做你喜欢的。

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);
    }
  }
}

这是可行的,因为 Moshi 允许您为和方法声明多个JsonAdapter参数,并且这些参数可以被注释。@ToJson@FromJson

如果类型相同,它还依赖于此功能的工作方式。在这里,我们JsonAdapter<LocalDateTime>通过委托给 another来制作 a JsonAdapter<LocalDateTime>。当类型相同时,Moshi 使用其nextAdapter()功能进行组合。

于 2018-04-11T02:19:21.143 回答