我最近开始在我的Android应用程序中使用Moshi,但我很想知道有关@JsonClass(generateAdapter = true)注释实际功能的更多信息。

数据类示例:

data class Person(
    val name: String
)

我可以按如下方式序列化/反序列化此类:
val moshi: Moshi = Moshi.Builder().build()
moshi.adapter(Person::class.java).toJson(Person())

我是而不是,在这里使用@JsonClass批注,因此代码生成将无法启动。

我的问题是,为什么和何时需要使用@JsonClass(generateAdapter = true)

最佳答案

Moshi的早期版本不支持“codegen”,因此它们完全依赖于反射(即在运行时自省(introspection)类的能力)。但是,这对于需要非常高性能的应用程序可能是个问题,因此他们添加了利用注释处理的“codegen”功能。基本上,这允许在编译时生成代码,因此它们可以在不使用反射的情况下执行序列化/反序列化。

为了启用代码生成功能,您还需要启用Kapt,它是Kotlin注释处理器,否则将不会进行任何注释处理。

Here您将找到如何启用和配置Kapt,而here您将找到如何设置Moshi codegen依赖项。

编辑

在您添加到问题的代码片段中,Moshi使用ClassJsonAdapter序列化您的对象。该适配器利用反射来查找所有字段并创建JSON字符串(您可以看到该类从java.lang.reflect导入东西)。

另一方面,Moshi代码生成会为您的类生成一个JsonAdapter。例如,让Moshi为您的Person类创建适配器将生成以下内容:

// Code generated by moshi-kotlin-codegen. Do not edit.
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonDataException
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import java.lang.NullPointerException
import kotlin.String

class PersonJsonAdapter(moshi: Moshi) : JsonAdapter<Person>() {
    private val options: JsonReader.Options = JsonReader.Options.of("name")

    private val stringAdapter: JsonAdapter<String> =
            moshi.adapter<String>(String::class.java, kotlin.collections.emptySet(), "name")

    override fun toString(): String = "GeneratedJsonAdapter(Person)"

    override fun fromJson(reader: JsonReader): Person {
        var name: String? = null
        reader.beginObject()
        while (reader.hasNext()) {
            when (reader.selectName(options)) {
                0 -> name = stringAdapter.fromJson(reader) ?: throw JsonDataException("Non-null value 'name' was null at ${reader.path}")
                -1 -> {
                    // Unknown name, skip it.
                    reader.skipName()
                    reader.skipValue()
                }
            }
        }
        reader.endObject()
        var result = Person(
                name = name ?: throw JsonDataException("Required property 'name' missing at ${reader.path}"))
        return result
    }

    override fun toJson(writer: JsonWriter, value: Person?) {
        if (value == null) {
            throw NullPointerException("value was null! Wrap in .nullSafe() to write nullable values.")
        }
        writer.beginObject()
        writer.name("name")
        stringAdapter.toJson(writer, value.name)
        writer.endObject()
    }
}

结果,当您要求Person的适配器时,Moshi将使用生成的PersonJsonAdapter而不是ClassJsonAdapter

奖金

Moshi uses reflection to instantiate the generated adapter(然后将其缓存,以便下次您请求同一类的适配器时可以重新使用),因此,如果您想使用codegen功能,则根本不需要添加任何额外的代码。

关于json - Moshi的Kotlin码本有什么用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58501918/

10-13 06:12