kotlin StringBuilder和URLEncoder -编码有问题吗?

huwehgph  于 2022-12-04  发布在  Kotlin
关注(0)|答案(1)|浏览(210)

我在使用URLEncoder编码部分和URL时遇到问题。
假设我有:

override suspend fun getData(ids: String): SomeData {
    val itemIds = ids.split(",").iterator()
    val sb = StringBuilder()
    sb.append("/v1/data?ids=")
    itemIds.forEach {
        val assetsJson = myObjectMapperWrapper.getObjectMapper().writeValueAsString(
            DataRequest(type = "Picture", id = it)
        )
        sb.append(URLEncoder.encode(assetsJson, Charsets.UTF_8))
        if (itemIds.hasNext()) sb.append("&data=")
    }
    val uri = sb.toString()

例如,assetsJson看起来如下所示:{"type":"Picture","id":" 12345"}id字段中的空格是有意的,因为这是一个String,出于未知的原因需要这些空格(这是一个API)。
使用在线工具对该字符串进行编码,得到以下结果:
图片类型
它以%7B%22开头,空格用%20表示。将其粘贴到用于在Inomnia中调用API的URI中是有效的。
使用调试器,我发现:编码为:
图片类型
所以没有%20为空格字符,而是+为符号。
最后一个问题是真正发送到服务器的内容:
图片类型图片
它是%257B%2522而不是%7B&22,是+而不是%20。即使在失眠症中,这也不起作用,API服务器返回:
无法将类型“java.lang.String[]”的值转换为所需类型“java.util. Set”;嵌套的异常是java.lang.IllegalArgumentException:com.fasterxml.jackson.core.JsonParseException:意外字符(' %'(代码37)):[源:]处应为有效值(JSON字符串、数字、数组、对象或标记“null”、“true”或“false”)(字符串)”图片类型“;行:1,列:2]
值得注意的是,空格字符看起来很正常:,而不是`+`(如由`StringBuilder`创建的)或`%20`(如由联机工具创建的)。 此堆栈跟踪中的字符串为`%7B%22type%22%3A%22Picture%22%2C%22id%22%3A%22 12345%22%7D"`,它接近于:`>%7B%22type%22%3A%22Picture%22%2C%22id%22%3A%22%20%20%20%20%20%20%20%20%2012345%22%7D`,但只有一个空格而不是9,并且它由正则空间而不是%20+表示。
我该怎么补救?我做错什么了吗?

vmdwslir

vmdwslir1#

看起来您正在尝试对作为API请求的查询字符串的一部分发送的JSON对象进行编码。此JSON对象不应进行编码,因为它需要采用API可以理解的格式。相反,您应该只对查询字符串中的单个参数进行编码,例如ids参数。
下面是一个如何执行此操作的示例:

override suspend fun getData(ids: String): SomeData {
// Split the IDs on commas
val itemIds = ids.split(",").iterator()
// Create a new StringBuilder to build the URL
val sb = StringBuilder()
// Append the base URL and the first parameter
sb.append("/v1/data?ids=")
// Loop through the IDs
itemIds.forEach {
// Create a DataRequest object with the current ID
val dataRequest = DataRequest(type = "Picture", id = it)
// Convert the object to a JSON string
val assetsJson = myObjectMapperWrapper.getObjectMapper().writeValueAsString(dataRequest)
// Encode the ID parameter and append it to the URL
sb.append(URLEncoder.encode(it, Charsets.UTF_8))
// If there are more IDs, append the data parameter and value
if (itemIds.hasNext()) sb.append("&data=")
}
// Create the URL from the StringBuilder
val uri = sb.toString()
// ...
}

在这个例子中,各个ID被编码并附加到查询字符串中,而JSON对象没有被编码。这应该产生一个API可以正确理解和处理的URL。
希望这对你有帮助!

相关问题