📜  适用于 Android 的 Moshi 库(1)

📅  最后修改于: 2023-12-03 15:12:21.238000             🧑  作者: Mango

适用于 Android 的 Moshi 库

Moshi 是一种现代的 JSON 库,用于在 Java 和 Kotlin 中序列化和反序列化 JSON 数据。它可以将 JSON 字符串转换为对象,也可以将对象转换为 JSON 字符串。Moshi 支持使用注解来控制序列化和反序列化行为,同时也支持自定义类型适配器和 JSON 转换器。

特点
快速

Moshi 的性能非常好,它甚至比一些老牌的 JSON 库更快。这得益于 Moshi 在解析和序列化过程中采用了少量的反射、优化和缓存策略。

灵活

Moshi 具有非常灵活的支持自定义类型适配器和 JSON 转换器。这使得 Moshi 能够处理符合你需求的数据格式。

支持 Kotlin

Moshi 与 Kotlin 非常兼容。它可以直接序列化和反序列化 Kotlin 的数据类,并支持使用 Kotlin 的默认值、可空类型和枚举等特性。

使用简单

Moshi 提供非常简单的 API,使得使用它变得非常容易。它可以直接与 Retrofit 和 OkHttp 进行集成,方便你快速地将 JSON 数据转换为对象。

使用步骤
添加依赖
implementation 'com.squareup.moshi:moshi:1.12.0'
创建序列化/反序列化器
val moshi = Moshi.Builder()
    // 添加自定义的类型适配器等
    .build()
将 JSON 字符串转换为对象
val jsonString = "{ \"name\": \"Moshi\", \"age\": 3 }"
val adapter = moshi.adapter(MyData::class.java)
val data: MyData? = adapter.fromJson(jsonString)
将对象转换为 JSON 字符串
val myData = MyData("Moshi", 3)
val adapter = moshi.adapter(MyData::class.java)
val jsonString: String = adapter.toJson(myData)
注解

Moshi 支持使用注解来控制序列化和反序列化行为。

data class MyData(
    val name: String,
    @Json(name = "years_old") val age: Int
)

@Json(name = "years_old") 指定了 JSON 字段名与类属性名不一致时的对应关系。

自定义类型适配器

当 JSON 数据结构与对象数据结构不完全匹配时,你需要使用 Moshi 提供的自定义类型适配器来完成转换。

class MyDataJsonAdapter : JsonAdapter<MyData>() {

  @Throws(IOException::class)
  override fun fromJson(reader: JsonReader): MyData? {
    var name: String? = null
    var age = 0
    reader.beginObject()
    while (reader.hasNext()) {
      when (reader.nextName()) {
        "name" -> name = reader.nextString()
        "age" -> age = reader.nextInt()
      }
    }
    reader.endObject()
    return MyData(name ?: return null, age)
  }

  @Throws(IOException::class)
  override fun toJson(writer: JsonWriter, value: MyData?) {
    writer.beginObject()
    writer.name("name").value(value!!.name)
    writer.name("age").value(value.age)
    writer.endObject()
  }

}
自定义 JSON 转换器

Moshi 提供了自定义 JSON 转换器的接口来让你自己控制 JSON 数据的序列化和反序列化。

class MyConverterFactory : Converter.Factory() {

  override fun responseBodyConverter(
    type: Type,
    annotations: Array<Annotation>,
    retrofit: Retrofit
  ): Converter<ResponseBody, *>? {
    val adapter = moshi.adapter(type)
    return Converter { value -> adapter.fromJson(value.string()) }
  }

  override fun requestBodyConverter(
    type: Type,
    parameterAnnotations: Array<Annotation>,
    methodAnnotations: Array<Annotation>,
    retrofit: Retrofit
  ): Converter<*, RequestBody>? {
    val adapter = moshi.adapter(type)
    return Converter { value -> adapter.toJson(value).toRequestBody(MEDIA_TYPE) }
  }

  companion object {
    private val MEDIA_TYPE = "application/json; charset=UTF-8".toMediaType()
  }

}
混淆规则

Moshi 使用反射来解析 JSON 数据和生成 JSON 字符串,因此在混淆时需要保护 Moshi 库的类不被删除或混淆掉。

-keep class com.squareup.moshi.** { *; }
结论

Moshi 是一个非常好用的 JSON 库,它具有良好的性能、灵活的支持和简单易用的 API。如果你需要在 Android 中使用 JSON 数据,Moshi 绝对是一个值得推荐的选择。