改造会从Map <string:=“” any =“”>生成错误的GET请求参数

时间:2018-12-10 20:08:58

标签: android kotlin retrofit okhttp3

我有以下数据:

var dict: Map<String, Any> = listOf()
dict["p1"] = listOf(1, 3)
dict["p2"] = listOf(null, 2.1)
dict["p3"] = 1

当我将此数据传递给以下函数时:

@GET("uri?staticKey=staticValue")
fun testApi(@QueryMap(encoded = true) params: @JvmSuppressWildcards Map<String, Any>): Call<ResponseBody>

我希望请求网址为:

uri?staticKey=staticValue&
    p1[0]=1&p1[1]=3&
    p2[0]=&p2[1]=2.1&
    p3=1

但这是它产生的东西:

uri?staticKey=staticValue&
    p1=[1, 3]&
    p2=[null, 2.1]&
    p3=1

我做错什么了吗?我刚刚开始Kotlin和Android的开发,所以我不确定Retrofit / okhttp库是否支持此功能。

注意:我需要Map<String, Any>之类的功能,以便轻松添加/删除查询参数。

2 个答案:

答案 0 :(得分:0)

改造只是调用toString()的值上的Map<String, Any>。要实现您想要的目标,必须直接对其进行定义

var dict: Map<String, Any> = listOf()
dict["p1[0]"] = 1
dict["p1[1]"] = 3
dict["p2[0]"] = ""
dict["p2[1]"] = 2.1
dict["p3"] = 1

您只需将地图展平就可以映射地图

fun Map<String, Any>.queryArgs(): Map<String, Any> {
    val map = mutableMapOf<String, Any>()
    forEach { (key, value) ->
        if (value !is Iterable<*>) {
            map[key] = value
        } else value.forEachIndexed { index, value ->
            map["$key[$index]"] = value ?: ""
        }
    }
    return map
}

这假设最多只列出一个列表。

答案 1 :(得分:0)

这是我提供的解决方案


  • HashMap中的原始键,因此可以进行更新/删除,例如

    dict.remove("p1")
    dict["p1"] = new value
    
  • 具有嵌套数组的能力,例如

    [
      0: [coord1, coord2, coord3],
      1: [coord1, coord2, coord3]
    ]
    

data class URL(val params: MutableMap<String, Any> = mutableMapOf<String, Any>()) {

    override fun toString(): String = params.map {
        val value = it.value
        if (value !is Iterable<*>) {
            it.key + "=" + it.value.toString()
        } else {
            createPairs(it.key, value)
        }
    }.joinToString("&")

    fun createPairs(key: String, value: Iterable<*>): String {
        return value.mapIndexed { idx, value ->
            val useKey = key + "[" + idx + "]"
            if (value !is Iterable<*>) {
                useKey + "=" + (value?.toString() ?: "")
            } else
                createPairs(useKey, value)

        }.joinToString("&")
    }
}

用法:

val url = URL()
url.params["p1"] = listOf(1, 3)
url.params["p2"] = listOf(null, 2.1)
url.params["p3"] = 1

val polygon1 = listOf("p1-coord1", "p1-coord2")
val polygon2 = listOf("p2-coord1", "p2-coord2", "p2-coord3")
val polygon3 = listOf("p3-coord1", "p3-coord2")
url.params["bbox"] = listOf(polygon1, polygon2, polygon3)

println(url.toString())

输出:

p1[0]=1&p1[1]=3&
p2[0]=&p2[1]=2.1&
p3=1&
bbox[0][0]=p1-coord1&bbox[0][1]=p1-coord2&
bbox[1][0]=p2-coord1&bbox[1][1]=p2-coord2&bbox[1][2]=p2-coord3&
bbox[2][0]=p3-coord1&bbox[2][1]=p3-coord2