我正在将gson迁移到moshi,但我在序列化列表时遇到了问题.我对"普通"对象没有问题,但对列表有问题.
我有一个类ImageDTO(包括一个Moshi适配器),如下所示:
class ImageDTO (
val idImage: String = "",
val idQuestion: String = "",
val image: String = "",
val timestamp: Int = 0,
var saveMode: String = ""
) {
@JsonClass(generateAdapter = true)
class ImageDTOIntermediate(
@Json(name = "idImage")
val idImage: String,
@Json(name = "idQuestion")
val idQuestion: String,
@Json(name = "image")
val image: String,
@Json(name = "timestamp")
val timestamp: Int,
@Json(name = "saveMode")
var saveMode: String = ""
)
companion object {
val JSON_ADAPTER: Any = object : Any() {
@ToJson
private fun toJson(imageDTO: ImageDTO): String {
val idImage = imageDTO.idImage
val idQuestion = imageDTO.idQuestion
val image = imageDTO.image
val timestamp = imageDTO.timestamp
val saveMode = imageDTO.saveMode
val imageDTOIntermediate = ImageDTOIntermediate(idImage, idQuestion, image, timestamp, saveMode)
return imageDTOIntermediate.serialize()
}
@FromJson
private fun fromJson(imageDTOIntermediate: ImageDTOIntermediate): ImageDTO {
val idImage = imageDTOIntermediate.idImage
val idQuestion = imageDTOIntermediate.idQuestion
val image = imageDTOIntermediate.image
val timestamp = imageDTOIntermediate.timestamp
val saveMode = imageDTOIntermediate.saveMode
return ImageDTO(idImage, idQuestion, image, timestamp, saveMode)
}
}
}
}
在序列化时,我希望接下来会有一个这样的Json:
[
{
"idImage":"f3d4befc-4569-c0c5-19b1-2865fcab5d33",
"idQuestion":"65d5254b-cb6d-a099-9f6d-71d93dcdcadb",
"image":"65d5254b-cb6d-a099-9f6d-71d93dcdcadb_q5_1.png",
"saveMode":"",
"timestamp":1498856479
},
{
"idImage":"66eb6535-f4b2-a130-6e90-cf53ce95bb63",
"idQuestion":"d23f87c0-cbc5-84b8-34cd-f5be4faced21",
"image":"d23f87c0-cbc5-84b8-34cd-f5be4faced21_i4_1.png",
"saveMode":"",
"timestamp":1538922258
},
{
"idImage":"016bba85-a023-8fb0-5aa4-71a0665dab94",
"idQuestion":"ad8e3eec-bd5a-aefa-fedf-28d51d82ab49",
"image":"ad8e3eec-bd5a-aefa-fedf-28d51d82ab49_i5_1.png",
"saveMode":"",
"timestamp":1626640944
}
]
以这种方式使用gson:
private var images: List<ImageDTO>
...
Gson().toJson(images)
我成功地获得了预期的Json,但是使用上面给出的适配器使用Moshi,我得到了一个表面上正确的Json字符串,但带有转义的双引号(\"),这对我来说是有意义的,因为适配器中的Serialize in ToJson方法.每个单独的ImageDTO对象都被正确地序列化,但是在构建列表时,最终的字符串已经对所有内部双引号进行了转义,我不知道如何处理这个问题.
下面是我的Moshi/Json扩展类:
object TMJson {
val moshi: Moshi = Moshi.Builder()
.add(User.JSON_ADAPTER)
.add(ImageDTO.JSON_ADAPTER)
.build()
inline fun <reified T> T.serialize(): String {
val adapter: JsonAdapter<T> = moshi.adapter(T::class.java)
return adapter.toJson(this)
}
inline fun <reified T> String.deserialize(): T? {
val adapter: JsonAdapter<T> = moshi.adapter(T::class.java)
return adapter.fromJson(this)
}
inline fun <reified T> String.serialize(): MutableList<T>? {
return moshi.serialize(this)
}
inline fun <reified T> Moshi.serialize(jsonString: String): MutableList<T>? {
return adapter<MutableList<T>>(Types.newParameterizedType(List::class.java, T::class.java)).fromJson(jsonString)
}
}
我想我的Moshi适配器可以简化,但不确定具体如何简化,这不是我的主要问题,而是像这样序列化的列表(为了简单起见,我不在这里放值:
["{\"idImage\":\"\",\"idQuestion\":\"\",\"image\":\"\",\"timestamp\":0,\"saveMode\":\"\"}","{\"idImage\":\"\",\"idQuestion\":\"\",\"image\":\"\",\"timestamp\":0,\"saveMode\":\"\"}","{\"idImage\":\"\",\"idQuestion\":\"\",\"image\":\"\",\"timestamp\":0,\"saveMode\":\"\"}","{\"idImage\":\"\",\"idQuestion\":\"\",...]
我不想使用KotlinJsonAdapterFactory(),而是使用定制适配器,因为它速度更快.
在我的build.gradle中:
implementation('com.squareup.moshi:moshi-kotlin:1.15.0')
ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.0")
对我的列表进行正确的序列化有什么帮助吗?
编辑1:这是我调用json/moshi扩展的方式.
private var images: List<ImageDTO>?
...
override fun call(): String {
images = getImagesFromTests(testsDTO)
val images1 = Gson().toJson(images) //=> Works
val images2 = images!!.serialize1() //=> Does not work
val tests = updateLocalDatabaseTests(testsDTO)
return "{\"tests\": [$tests], \"images\": [$images1]}"
}
我必须补充的是,"Call"方法是一个后台任务,当调用"Call"方法时,图像(ImageDTO列表)已经有了值.
编辑2:关于项目的额外信息.
我不认为这是相关的,但以防万一,我会补充说,我的应用程序是一个多模块的应用程序.类"ImageDTO"位于MyApp.DTO模块中,而TMJson扩展位于MyApp.Common模块中.
由于循环依赖,我不能在"DTO"中引用"Common",所以我最后用Serialize方法克隆了"TMJson"扩展类.
让我困惑的是,在根本没有数据修改的情况下,需要使用中间对象来进行序列化,但这是我在网上找到的一个例子,这是我知道的唯一做到这一点的方法.