首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带接口的KTor Gson DataConversion

带接口的KTor Gson DataConversion
EN

Stack Overflow用户
提问于 2018-11-17 11:47:37
回答 1查看 863关注 0票数 0

我正在尝试注册PubicKey接口,以便在KTor中进行数据转换,这样我就可以很容易地接收到这样的公钥:

代码语言:javascript
运行
复制
data class StoreRequest(
    val publicKey: PublicKey
)
...
val publicKey: PublicKey = call.receive<StoreRequest>().publicKey

为此,我使用了以下页面:https://ktor.io/servers/features/data-conversion.html

我注册了这个数据转换器:

代码语言:javascript
运行
复制
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抱怨是因为我使用的是一个接口:

代码语言:javascript
运行
复制
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类:

代码语言:javascript
运行
复制
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 })
    }
}

但这也没用!这是我得到的例外:

代码语言:javascript
运行
复制
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 2 column 16 path $.publicKey

由于某些原因,它希望提供的密钥是JSON对象,而我提供的是:

代码语言:javascript
运行
复制
{
    "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== dynmem@memmen.frl"
}

我如何“欺骗”GSON在PublicKey中接受字符串?还是我做错了什么?

我认为GSON希望将JSON对象序列化为PublicKey。但我想让它接受String。我认为这是可能的,因为像UUIDDate这样的类工作得很好.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-17 12:41:38

我解决了!我没有使用InstanceCreator,而是使用了JsonDeserializer

代码语言:javascript
运行
复制
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)
        })
    }
}

这部分可以完全移除:

代码语言:javascript
运行
复制
convert<PublicKey> {
    decode { values, _ ->
        ...
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53350924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档