web-dev-qa-db-ja.com

文字列の日付をjsonからMoshiでDateオブジェクトに変換します

gsonであなたはこれをするでしょう

Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd'T'HH:mm")
            .create();

それをレトロフィットビルダーに渡すと、GsonがDateオブジェクトを作成します。kotlinクラスでもこれを行うためにMoshiを取得する方法はありますか?

12
tyczj

標準のISO-8601/RFC 3339日付アダプターを使用する場合(おそらく使用します)、組み込みのアダプターを使用できます。

Moshi moshi = new Moshi.Builder()
    .add(Date.class, new Rfc3339DateJsonAdapter().nullSafe())
    .build();

JsonAdapter<Date> dateAdapter = moshi.adapter(Date.class);
assertThat(dateAdapter.fromJson("\"1985-04-12T23:20:50.52Z\""))
    .isEqualTo(newDate(1985, 4, 12, 23, 20, 50, 520, 0));

これを機能させるには、このMaven依存関係が必要です。

<dependency>
  <groupId>com.squareup.moshi</groupId>
  <artifactId>moshi-adapters</artifactId>
  <version>1.5.0</version>
</dependency>

カスタムフォーマットを使用したい場合(おそらく使用しない場合)は、さらにコードがあります。日付を受け入れて文字列にフォーマットするメソッドと、文字列を受け入れて日付として解析する別のメソッドを記述します。

Object customDateAdapter = new Object() {
  final DateFormat dateFormat;
  {
    dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
  }

  @ToJson synchronized String dateToJson(Date d) {
    return dateFormat.format(d);
  }

  @FromJson synchronized Date dateToJson(String s) throws ParseException {
    return dateFormat.parse(s);
  }
};

Moshi moshi = new Moshi.Builder()
    .add(customDateAdapter)
    .build();

JsonAdapter<Date> dateAdapter = moshi.adapter(Date.class);
assertThat(dateAdapter.fromJson("\"1985-04-12T23:20\""))
    .isEqualTo(newDate(1985, 4, 12, 23, 20, 0, 0, 0));

synchronizedはスレッドセーフではないため、SimpleDateFormatを使用することを忘れないでください。また、SimpleDateFormatのタイムゾーンを設定する必要があります。

24
Jesse Wilson

Kotlinでは、JsonAdapterクラスを拡張して、独自のアダプターを作成できます。

class CustomDateAdapter : JsonAdapter<Date>() {
    private val dateFormat = SimpleDateFormat(SERVER_FORMAT, Locale.getDefault())

    @FromJson
    override fun fromJson(reader: JsonReader): Date? {
        return try {
            val dateAsString = reader.nextString()
            dateFormat.parse(dateAsString)
        } catch (e: Exception) {
            null
        }
    }

    @ToJson
    override fun toJson(writer: JsonWriter, value: Date?) {
        if (value != null) {
            writer.value(value.toString())
        }
    }

    companion object {
        const val SERVER_FORMAT = ("yyyy-MM-dd'T'HH:mm") // define your server format here
    }
}

次に、Retrofitの初期化で、次のようにしてMoshi.Builderを使用してアダプターを設定できます。

 private val moshiBuilder = Moshi.Builder().add(CustomDateAdapter()) // Your custom date adapter here

        val service: ApiService by lazy {
            val loggingInterceptor = HttpLoggingInterceptor()
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY

            val httpClient = OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build()

            val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.API_URL)
                .client(httpClient)
                .addConverterFactory(MoshiConverterFactory.create(moshiBuilder.build()))
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .build()

            retrofit.create(ApiService::class.Java)
        }
2
Nicola Gallazzi