带接口的 KTor Gson 数据转换

扬·维茨

我正在尝试PubicKey在 KTor 中注册用于数据转换接口,以便我可以轻松接收这样的公钥:

data class StoreRequest(
    val publicKey: PublicKey
)
...
val publicKey: PublicKey = call.receive<StoreRequest>().publicKey

为了实现这一点,我使用了这个页面:https : //ktor.io/servers/features/data-conversion.html
我注册了这个数据转换器:

convert<PublicKey> {
    decode { values, _ ->
        // When I add a breakpoint here it won't be reached.
        values.singleOrNull()?.let { key ->
            val encryptedKey = Base64.getDecoder().decode(key.split(" ")[1])
            val inputStream = DataInputStream(ByteArrayInputStream(encryptedKey))

            val format = String(ByteArray(inputStream.readInt()).also(inputStream::readFully))

            if (format != "ssh-rsa") throw RuntimeException("Unsupported format")

            val publicExponent = ByteArray(inputStream.readInt()).also(inputStream::readFully)
            val modulus = ByteArray(inputStream.readInt()).also(inputStream::readFully)

            val spec = RSAPublicKeySpec(BigInteger(modulus), BigInteger(publicExponent))
            val keyFactory = KeyFactory.getInstance("RSA")

            keyFactory.generatePublic(spec)
        }
    }
}

但出于某种原因,Gson 抱怨,因为我正在使用一个接口:

java.lang.RuntimeException: Unable to invoke no-args constructor for interface java.security.PublicKey. Register an InstanceCreator with Gson for this type may fix this problem`

所以我猜我需要InstanceCreator为初始值创建一个这是PublicKey我创建的初始类:

class PkTest : PublicKey {
    override fun getAlgorithm(): String = ""
    override fun getEncoded(): ByteArray = ByteArray(0)
    override fun getFormat(): String = ""
}
...
install(ContentNegotiation) {
    gson {
        setPrettyPrinting()
        registerTypeAdapter(PublicKey::class.java, InstanceCreator<PublicKey> { PkTest() // This is called when I add a breakpoint })
    }
}

但这也行不通!这是我得到的例外:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 2 column 16 path $.publicKey

出于某种原因,它期望提供的密钥是一个 JSON 对象,而我提供这个:

{
    "publicKey": "ssh-rsa AAAAB3NzaC1yc2EABAADAQABAAACAQDBPL2s+25Ank3zS6iHUoVk0tS63dZM0LzAaniiDon0tdWwq4vcL4+fV8BsAEcpMeijS92JhDDc9FccXlHbdDcmd6c4ITOt9h9xxhIefGsi1FTVJ/EjVtbqF5m0bu7ruIMGvuP1p5s004roHx9y0UdHvD/yNWLISMhy4nio6jLailIj3FS53Emj1WRNsOrpja3LzPXzhuuj6YnD9yfByT7iGZipxkmleaXrknChPClLI9uhcqtAzBLdd0NVTJLOt/3+d1cSNwdBw9e53wJvpEmH+P8UOZd+oV/y7cHIej4jQpBXVvpJR1Yaluh5RuxY90B0hSescUAj5g/3HVPpR/gE7op6i9Ab//0iXF15uWGlGzipI4lA2/wYEtv8swTjmdCTMNcTDw/1huTDEzZjghIKVpskHde/Lj416c7eSByLqsMg2OhlZGChKznpIjhuNRXz93DwqKuIKvJKSnhqaJDxmDGfG7nlQ/eTwGeAZ6VR50yMPiRTIpuYd767+Nsg486z7p0pnKoBlL6ffTbfeolUX2b6Nb9ZIOxJdpCSNTQRKQ50p4Y3S580cUM1Y2EfjlfIQG1JdmTQYB75AZXi/cB2PvScmF0bXRoj7iHg4lCnSUvRprWA0xbwzCW/wjNqw6MyRX42FFlvSRrmfaxGZxKYbmk3TzBv+Fp+CADPqQm3OQ== [email protected]"
}

我怎样才能“欺骗” GSON 接受一个字符串PublicKey还是我做错了什么?

我认为 GSON 想将 JSON 对象序列化为PublicKey. 但我希望它接受一个String. 我认为这应该是可能的,因为类喜欢UUID并且Date工作得很好......

扬·维茨

我解决了!而不是使用一个InstanceCreator我使用了一个JsonDeserializer

install(ContentNegotiation) {
    gson {
        setPrettyPrinting()
        registerTypeAdapter(PublicKey::class.java, JsonDeserializer<PublicKey> { json, _, _ ->
            // TODO some type checking.
            val key = json.asString
            val encryptedKey = Base64.getDecoder().decode(key.split(" ")[1])
            val inputStream = DataInputStream(ByteArrayInputStream(encryptedKey))

            val format = String(ByteArray(inputStream.readInt()).also(inputStream::readFully))

            if (format != "ssh-rsa") throw RuntimeException("Unsupported format")

            val publicExponent = ByteArray(inputStream.readInt()).also(inputStream::readFully)
            val modulus = ByteArray(inputStream.readInt()).also(inputStream::readFully)

            val spec = RSAPublicKeySpec(BigInteger(modulus), BigInteger(publicExponent))
            val keyFactory = KeyFactory.getInstance("RSA")

            keyFactory.generatePublic(spec)
        })
    }
}

这部分可以完全删除:

convert<PublicKey> {
    decode { values, _ ->
        ...
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Gson从Json转换为带日期的arraylist

来自分类Dev

带 USB 音频接口的音高转换

来自分类Dev

ktor为某些数据类抛出NoTransformationFoundException

来自分类Dev

Java gson 转换错误

来自分类Dev

使用 GSON 进行转换

来自分类Dev

如何使用gson将json数据转换为java对象?

来自分类Dev

用GSON读写数据

来自分类Dev

用GSON读写数据

来自分类Dev

Ktor-根据Wordpress数据库检查密码

来自分类Dev

将Gson转换为对象?

来自分类Dev

Gson无法转换api响应

来自分类Dev

Gson Class强制转换例外

来自分类Dev

科特林数据类转换与GSON ...和默认值是通过转换为零或空

来自分类Dev

GSON解析以更改json数据

来自分类Dev

使用GSON解析JSON数据

来自分类Dev

GSON解析以更改json数据

来自分类Dev

如何使用gson处理动态响应数据?(JSON转换为Java对象)

来自分类Dev

使用Gson从JSON字符串转换为数据类对象列表?

来自分类Dev

使用GSON将JSON数据转换为Java对象(包括Object类)

来自分类Dev

Gson序列化:如何在其中强制转换通用类和通用数据?

来自分类Dev

带接口的JsonConverter

来自分类Dev

带接口的instanceof

来自分类Dev

带接口的 Laravel DI

来自分类Dev

Gson到JSON字符串转换

来自分类Dev

Gson转换返回空Java对象

来自分类Dev

Gson从JSON转换为Java对象

来自分类Dev

Gson到JSON字符串转换

来自分类Dev

Gson转换返回空Java对象

来自分类Dev

Gson 在转换时忽略我的字段