【问题标题】:How do you serialize a list of BufferedImage in Kotlin?如何在 Kotlin 中序列化 BufferedImage 列表?
【发布时间】:2022-08-19 05:37:02
【问题描述】:

我正在尝试实现一个协议,其中(部分)通过套接字发送小图像列表。我正在使用 JSON,并且图像是 base64 编码的。

这是数据类

@Serializable
sealed class CmdBase {
    abstract val cmd: Command
}

@Serializable
@SerialName(\"CmdIdImgs\")
class CmdIdImgs(
    override val cmd: Command,
    val id: String,
    @Serializable(with = ImageListSerializer::class)
    val thumbnails: List<BufferedImage>) : CmdBase()

所以我为 BufferedImage 添加了一个序列化程序

object ImageSerializer: KSerializer<BufferedImage> {
    override val descriptor = PrimitiveSerialDescriptor(\"Image.image\", PrimitiveKind.STRING)

    override fun deserialize(decoder: Decoder): BufferedImage {
        val b64str = decoder.decodeString()
        return ImageIO.read(ByteArrayInputStream(Base64.getDecoder().decode(b64str)))
    }

    override fun serialize(encoder: Encoder, value: BufferedImage) {
        val buff = ByteArrayOutputStream()
        ImageIO.write(value, \"PNG\", buff)
        val b64str = Base64.getEncoder().encodeToString(buff.toByteArray())
        encoder.encodeString(b64str)
    }
}

但它是一个 BufferedImages 列表,所以我为此添加了一个序列化程序

class ImageListSerializer: KSerializer<List<BufferedImage>> {
    private val listSerializer = ListSerializer(ImageSerializer)
    override val descriptor: SerialDescriptor = listSerializer.descriptor

    override fun serialize(encoder: Encoder, value: List<BufferedImage>) {
        listSerializer.serialize(encoder, value)
    }

    override fun deserialize(decoder: Decoder): List<BufferedImage> = with(decoder as JsonDecoder) {
        decodeJsonElement().jsonArray.mapNotNull {
            try {
                json.decodeFromJsonElement(ImageSerializer, it)
            } catch (e: SerializationException) {
                e.printStackTrace()
                null
            }
        }
    }
}

现在是整个班级的序列化程序

object CmdIdImgsSerializer : SerializationStrategy<CmdIdImgs>, DeserializationStrategy<CmdIdImgs> {
    override val descriptor = buildClassSerialDescriptor(\"CmdIdImgs\") {
        element(\"cmd\", Command.serializer().descriptor)
        element(\"id\", String.serializer().descriptor)
        element(\"thumbnails\", ImageListSerializer().descriptor)
    }

    override fun serialize(encoder: Encoder, value: CmdIdImgs) {
        encoder.encodeStructure(descriptor) {
            encodeSerializableElement(descriptor, 0, Command.serializer(), value.cmd)
            encodeSerializableElement(descriptor, 1, String.serializer(), value.id)
            encodeSerializableElement(descriptor, 2, ImageListSerializer(), value.thumbnails)
        }
    }

    override fun deserialize(decoder: Decoder): CmdIdImgs =
        decoder.decodeStructure(descriptor) {
            var cmd: Command = Command.FULL_TREE
            var id: String = \"\"
            var thumbnails: List<BufferedImage> = listOf()
            loop@ while (true) {
                when (val i = decodeElementIndex(descriptor)) {
                    0 -> cmd = decodeSerializableElement(descriptor, i, Command.serializer())
                    1 -> id = decodeSerializableElement(descriptor, i, String.serializer())
                    2 -> thumbnails = decodeSerializableElement(descriptor, i, ImageListSerializer())
                    CompositeDecoder.DECODE_DONE -> break
                    else -> throw SerializationException(\"Unknown index $i\")
                }
            }
            CmdIdImgs(cmd, id, thumbnails)
        }
}

但有些事情是错误的,因为我仍然得到

未找到类型 \'BufferedImage\' 的序列化程序

在 CmdIdImgs 类中的 \'val thumbnails: List<BufferedImage>\'

知道我做错了什么吗?

可能很多,因为我是 Kotlin 的新手 :-)

    标签: json kotlin serialization jvm


    【解决方案1】:

    由于您想将 JSON 发送到您的套接字,我建议您使用事实上杰克逊。如果这对你来说没问题,那么这更简单——你只需要创建一个专门的序列化程序。这是工作代码(反序列化器 TODO)。

    import com.fasterxml.jackson.core.JsonGenerator
    import com.fasterxml.jackson.databind.SerializerProvider
    import com.fasterxml.jackson.databind.json.JsonMapper
    import com.fasterxml.jackson.databind.module.SimpleModule
    import com.fasterxml.jackson.databind.ser.std.StdSerializer
    import com.fasterxml.jackson.module.kotlin.KotlinModule
    import java.awt.image.BufferedImage
    import java.io.ByteArrayOutputStream
    import java.io.File
    import java.util.*
    import javax.imageio.ImageIO
    
    sealed class CmdBase {
        abstract val cmd: String // Command
    }
    
    class CmdIdImgs(
        override val cmd: String, // Command
        val id: String,
        val thumbnails: List<BufferedImage>,
    ) : CmdBase()
    
    class BufferedImageSerializer : StdSerializer<BufferedImage>(BufferedImage::class.java) {
        override fun serialize(value: BufferedImage?, jgen: JsonGenerator, provider: SerializerProvider?) {
            value?.let {
                val buff = ByteArrayOutputStream()
                ImageIO.write(it, "PNG", buff)
                val b64str = Base64.getEncoder().encodeToString(buff.toByteArray())
                jgen.writeString(b64str)
            }
        }
    }
    
    //class BufferedImageDeserializer : StdDeserializer<BufferedImage>(BufferedImage::class.java) {
    //    override fun deserialize(jp: JsonParser, ctxt: DeserializationContext?): BufferedImage? {
    //        val node: JsonNode = jp.codec.readTree(jp)
    //        if (!node.isTextual) {
    //            node.asText()....
    //        }
    //    }
    //}
    
    val IMAGE_MODULE = SimpleModule().apply {
        this.addSerializer(BufferedImage::class.java, BufferedImageSerializer())
        //this.addDeserializer(BufferedImage::class.java, BufferedImageDeserializer())
    }
    
    val MAPPER = JsonMapper.builder()
        .addModule(KotlinModule(strictNullChecks = true))
        .addModule(IMAGE_MODULE)
        .build()
    
    fun main(args: Array<String>) {
        val cmdIdImgs = CmdIdImgs("x", "1", listOf(ImageIO.read(File("/tmp/image.png"))))
        println(MAPPER.writeValueAsString(cmdIdImgs))
    }
    

    印刷

    {"cmd":"x","id":"1","thumbnails":["iVBORw0KGgoAAAAN....
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      相关资源
      最近更新 更多