在 moshi 中序列化时如何忽略字段?

How to ignore field when Serializing in moshi?

我是 Moshi 和 Kotlin 的新手,我实际上制作了两种方法,它们 returns 来自我的 Room 数据库的数据,并仅从两个对象制作一个,然后我将通过 Moshi 序列化。

有没有办法从序列化中忽略或删除某些字段?我尝试使用 @Transient 但由于我的模型结构引发了很多错误。

这是我的模型的样子:

@JsonClass(generateAdapter = true)
@Entity(tableName = "corpo", foreignKeys = [
    ForeignKey(
        entity = Testata::class,
        parentColumns = ["id"],
        childColumns = ["id_testata"],
        onDelete = CASCADE
    )
], indices = [ Index("id_testata") ], primaryKeys = [
    "barcode", "id_testata"
])
data class Corpo(
    var barcode: String,
    var desc: String?, // ignore this
    @ColumnInfo(defaultValue = "PZ")
    var um: String, // ignore this
    var qta: Float, 
    var id_testata: Int // i have to ignore this
)

@JsonClass(generateAdapter = true)
@Entity(tableName = "testata")
data class Testata(
    @PrimaryKey(autoGenerate = true)
    var id: Int,
    var cod: String,
    var tipo: String,
    var cod_fornitore: String,
    var desc_fornitore: String, // ignore this
    var data: String,
    var inviato: Boolean // ignore this
){
    constructor(cod: String, tipo: String, cod_fornitore: String, desc_fornitore: String, data: String, inviato: Boolean)
            : this(0, cod, tipo, cod_fornitore, desc_fornitore, data, inviato)
}

@JsonClass(generateAdapter = true) // this is my class which combine the two classes from Room db
data class Documento(
    var testata: Testata,
    var corpo: List<Corpo>
)

在这里我通过 Moshi 获得了我的序列化对象:

        val moshi = Moshi.Builder().build()
        val jsonAdapter: JsonAdapter<Documento> = moshi.adapter(Documento::class.java)
        val documento = Documento(corpoViewModel.selectTestata(testata.id), corpoViewModel.selectCorpo(testata.id))
        val json = jsonAdapter.toJson(documento)

此时我如何忽略我评论的字段并将它们从我的序列化中删除?

我看到 2 个适合您的用例的可行选项。

在您开始之前,您需要 2 个单独的 classes 用于所需的序列化 json,您可以选择:

  1. 使用映射器将一个 dto 映射到另一个。

  2. 使用 Moshi 的 Custom Type Adapter 来处理 TestataCorpo

    的映射

首先,定义两个想要的模型:

data class JsonCorpo(
    var barcode: String,
    var qta: Float, 
)

data class JsonTestata(
    var id: Int,
    var cod: String,
    var tipo: String,
    var cod_fornitore: String,
    var data: String,
)

并在组合 Documento class

中使用 JsonTestataJsonCorpo 而不是 TestataCorpo

选项 1

我通常有一个映射器界面。 如果你使用像 Dagger 这样的注入框架,这会很方便,因为你不必记住映射器的名称 class.

/**
 * Base mapper to convert [Input] type to [Output] type.
 */
interface Mapper<Input, Output> {
    /**
     * Transforms [input] into [Output].
     *
     * @param input the input to be transformed
     * @return transformation result [Output]
     */
    fun map(input: Input): Output

    /**
     * Transforms a [List] of [Input] into a [List] of [Output].
     *
     * @param input The input to be transformed
     * @return transformation result
     */
    fun map(input: List<Input>): List<Output> {
        val result: MutableList<Output> = LinkedList()
        for (item in input) {
            result.add(map(item))
        }
        return result
    }
}

并声明每个映射:

class CorpoToJsonCorpoMapper: Mapper<Corpo, SerializedCorpo> {
    
    override fun map(input: Corpo): SerializedCorpo = with(input) {
        SerializedCorpo(barcode, qta)
    }
}

class TestataToJsonTestataMapper: Mapper<Testata, SerializedTestata> {
    
    override fun map(input: Testata): SerializedTestata = with(input) {
        SerializedTestata(id, cod, tipo, cod_fornitore, data)
    }
}

然后你可以使用两个映射器来映射来自

的结果

corpoViewModel.selectTestata(testata.id)corpoViewModel.selectCorpo(testata.id)

选项 2

您让 Moshi 的适配器负责映射:

class CorpoJsonAdapter {
  @FromJson Event corpoFromJson(JsonCorpo jsonCorpo) {
    return Corpo(
       ...
       // Here handle the deserialization
    );
  }

  @ToJson JsonCorpo corpoToJson(Corpo corpo) {
     return JsonCorpo(corpo.barcode, corpo.qta)
  }
}

和类似声明 TestataJsonAdapter 来处理 Testata class.

的序列化和反序列化