首页 > 解决方案 > 在moshi中序列化时如何忽略字段?

问题描述

我是 Moshi 和 Kotlin 的新手,我实际上做了两种方法,它们从我的 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)

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

标签: androidkotlinmoshi

解决方案


我为您的用例看到了 2 个可行的选项。

在你走之前,你需要 2 个单独的类来获取所需的序列化 json,你可以选择:

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

  2. 使用 Moshi 的自定义类型适配器来处理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,
)

在你的组合类中使用JsonTestataandJsonCorpo而不是TestataandCorpoDocumento

选项1

我通常有一个映射器接口。如果您使用像 Dagger 这样的注入框架,这很方便,因为您不必记住映射器类的名称。

/**
 * 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)
  }
}

和类似的声明 aTestataJsonAdapter来处理Testata类的序列化和反序列化。


推荐阅读