如何使用Retrofit2将Map <String,Any>作为参数传递?

时间:2019-10-15 23:18:15

标签: android kotlin retrofit2

我需要传递Map<String, Any>作为PUT请求的参数。 Json(由Map制造)看起来像这样:

{
  "user": {
    "lastname": "Smith",
    "name": "John",
    ...
  },
  "foreign_language_keys": [
    "eng",
    "fr"
  ],
  "tachograph_cards": [
    {
      "tachograph_key": "estr",
      "tachograph_card_num":
      .....

如果我通过Map<String, String>作为参数-可以正常工作:

@FormUrlEncoded
@Headers("Content-Type: application/json")
@PUT("api/authorization/user/driver/{user_id}")
fun editUser(@Path("user_id") userId: String, @FieldMap body: Map<String, String>): Single<UserModel>

但是,如果我需要传递Map<String, Any>作为参数-我会收到运行时错误“ java.lang.IllegalArgumentException:参数类型不得包含类型变量或通配符:java.util.Map(参数#2)”

添加@JvmSuppressWildcards批注(@FieldMap body: Map<String, @JvmSuppressWildcards Any>))无济于事(我从服务器收到Json中必填字段之一的另一个错误“未定义索引”,因为服务器在我的请求中没有看到此字段)。

有效的解决方案是通过映射模型中的所有字段(而不是传递Map<String, Any>)来制作com.google.gson.JsonObject,但这太困难了。我确信它必须能够在不将模型转换为Json的情况下工作,但是我找不到简单的解决方案。 有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

您的JSON结构看起来很奇怪且不一致。您传递用于翻新的结构,您需要定义清晰一致的结构。在您的情况下,看起来您的映射键始终是String,但是映射的值部分有时是Json对象,有时是数组/列表或其他内容。不一致导致无法精确计算结构化价值。

您肯定不能发布/投放Map<String, Any,因为?是非法的论点。

您可以构造和发送Map<String, JsonObject>,如果您使用Gson库,则创建JsonObject并不困难。您要做的就是提取字符串(Json对象的值部分)并将其提供给Gson库,然后生成JsonObject模型供您传递。

或者您可以从解析端发送Map<String, String>parse())的Json值,{p​​}

答案 1 :(得分:0)

我最近也遇到了同样的问题,并且我发现了最简单的解决方案。 您可以在这里查看我对类似问题的完整答案:https://stackoverflow.com/a/61324340/7110268

在特定情况下,您可以尝试以下操作:

val body = mutableMapOf<String, String>()

body["user[lastname]"] = "Smith"
body["user[name]"] = "John"

body["foreign_language_keys[0]"] = "eng"
body["foreign_language_keys[1]"] = "fr"

// and so on

例如,如果您需要传递庞大的动态列表,则可以轻松地在for循环中填充地图。

答案 2 :(得分:-1)

它必须是一个可变变量作为委托属性。能够惩罚你想用 Any 放置的财产

你的解决方案是放置 MutableMap

interface MutableMap<K, V> 
    
V the type of map values. The mutable map is invariant in its value type.

interfaceMap<K, V> 
    
V the type of map values. The map is covariant in its value type.


@FormUrlEncoded
@Headers("Content-Type: application/json")
@PUT("api/authorization/user/driver/{user_id}")
fun editUser(@Path("user_id") userId: String, @FieldMap body: MutableMap<String, String>): Single<UserModel>