从Gson迁移到Moshi时序列化List<ImageDTO>遇转义问题求助
解决Moshi序列化List时内部双引号转义问题
问题根源
你的自定义ImageDTO适配器如果是直接返回字符串类型的JSON内容(比如手动拼接的JSON字符串),Moshi会将其视为普通字符串处理,序列化列表时自动转义字符串内部的双引号。而Gson会自动识别这类字符串为JSON结构,不会额外转义。
解决方案:调整自定义适配器,直接使用JsonWriter写入JSON结构
不要让适配器返回字符串,而是通过JsonWriter直接写入JSON对象的字段,这样Moshi在序列化列表时会将每个元素识别为JSON对象,而非字符串,避免转义。
修正后的ImageDTO适配器
class ImageDtoAdapter { @ToJson fun toJson(writer: JsonWriter, image: ImageDTO) { writer.beginObject() // 逐个写入字段,示例以url字段为例 writer.name("url").value(image.url) // 其他字段按同样方式写入,比如width、height等 // writer.name("width").value(image.width) writer.endObject() } @FromJson fun fromJson(reader: JsonReader): ImageDTO { var url = "" // 可根据需要添加其他字段的默认值 // var width = 0 reader.beginObject() while (reader.hasNext()) { when (val fieldName = reader.nextName()) { "url" -> url = reader.nextString() // "width" -> width = reader.nextInt() else -> reader.skipValue() // 跳过未知字段 } } reader.endObject() return ImageDTO(url) // 对应构造函数传入字段 } }
注册适配器到Moshi
val moshi = Moshi.Builder() .add(ImageDtoAdapter()) .build()
备选方案:自定义List适配器(复用原有字符串逻辑时)
如果必须保留基于字符串的序列化逻辑(比如复用原Gson的代码),可以单独为List<ImageDTO>编写适配器,手动处理每个元素的序列化,避免转义:
class ImageListAdapter(private val imageAdapter: ImageDtoAdapter) { @ToJson fun toJson(writer: JsonWriter, images: List<ImageDTO>) { writer.beginArray() images.forEach { image -> // 直接调用ImageDTO的写入逻辑,绕过字符串转义 imageAdapter.toJson(writer, image) } writer.endArray() } @FromJson fun fromJson(reader: JsonReader): List<ImageDTO> { val imageList = mutableListOf<ImageDTO>() reader.beginArray() while (reader.hasNext()) { imageList.add(imageAdapter.fromJson(reader)) } reader.endArray() return imageList } }
注册时注意顺序:
val moshi = Moshi.Builder() .add(ImageDtoAdapter()) .add(ImageListAdapter(ImageDtoAdapter())) .build()
验证效果
序列化列表时,Moshi会生成正确的JSON数组,内部字段的双引号不会被转义:
[{"url":"https://example.com/image.jpg"},{"url":"https://example.com/image2.jpg"}]
内容的提问来源于stack exchange,提问作者Diego Perez
相关产品推荐
相关产品推荐

