使用 Moshi 将字符串日期从 json 转换为 Date 对象
Posted
技术标签:
【中文标题】使用 Moshi 将字符串日期从 json 转换为 Date 对象【英文标题】:Turn string date from json to a Date object with Moshi 【发布时间】:2017-11-11 20:53:33 【问题描述】:使用 Gson 你会这样做
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm")
.create();
并将其传递给改造构建器,Gson 将为您创建一个 Date 对象,有没有办法让 Moshi
在 kotlin 类中也这样做?
【问题讨论】:
github.com/square/moshi/tree/master/adapters/src/main/java/com/… 会做你想做的事吗?该适配器发布在 moshi-adapters 工件中。 【参考方案1】:如果您想使用标准 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
配置时区。
【讨论】:
感谢您的回答。 :) 为了方便起见,这里是 Gradle 依赖项:implementation("com.squareup.moshi:moshi:1.8.0") implementation("com.squareup.moshi:moshi-adapters:1.8.0")
【参考方案2】:
在 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()
synchronized(dateFormat)
dateFormat.parse(dateAsString)
catch (e: Exception)
null
@ToJson
override fun toJson(writer: JsonWriter, value: Date?)
if (value != null)
synchronized(dateFormat)
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())) // And don`t forget to add moshi class when creating MoshiConverterFactory
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
retrofit.create(ApiService::class.java)
【讨论】:
您好,感谢您的回复,确实对我帮助很大!我想知道一件事:toJson 究竟什么时候起作用?fromJson
在获取属性时工作并返回 Date
但是我无法根据新格式操作此 Date
。我有这些格式; ``` private const val SERVER_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'" private const val APP_DATE_FORMAT = "yyyy-MM-dd" ``` 这个代码块没有工作 ``` @ToJson 覆盖 fun toJson(writer: JsonWriter, value: Date?) writer.value(appFormatter.format(value!!)) ```
toJson 对于将 POJO 类序列化为 json 格式很有用。假设需要从您的对象创建一个 json 文档,在这种情况下,您需要将序列化程序添加到您的 moshi 构建器中以上是关于使用 Moshi 将字符串日期从 json 转换为 Date 对象的主要内容,如果未能解决你的问题,请参考以下文章
将 UNIX 时间从 json 导入(swift 结构)转换为日期作为字符串并填充表
将 JSON 时间戳字符串转换为 pandas 数据框中的 python 日期