【问题标题】:Retrofit post data with nested request params使用嵌套请求参数改造帖子数据
【发布时间】:2020-01-24 04:05:17
【问题描述】:

目前我正在进行改造。我知道带有自定义对象以及普通和多表单数据的发布数据。但是我被卡住了,因为我想使用嵌套的请求参数将数据发布到服务器。

例如,

devicetype": "simulator",
"deviceid": "6ea09052e5b1fd10",
"appversion": "0.1",
"apiversion": "0.1",

我可以将其作为RequestBody 字符串发布,因为我希望使用多格式数据发布带有图像的数据。所以我已经清除了这个概念。

但现在我有另一个自定义数据。

  "sitedetail": {
    "id": "1",
    "name": "xxx",
    "visitorid": "1"
},

那么我怎样才能将它作为请求参数传递。确实需要传递一个 @Body,我们通常将其作为自定义数据或 json 数据传递。我卡在这里了。

更新

{
"devicetype": "simulator",
"deviceid": "6ea09052e5b1fd10",
"appversion": "0.1",
"apiversion": "0.1",
"timezone": "Asia/Kolkata",
"modeltype": "MI A1",
"deviceos": "9.0",
"userdeviceid": "1",
"visitorid": "1",
"siteid": "1",
"visitordetail": {
    "id": "1",
    "userid": "2",
    "name": "xxx",
    "email": "xxx@xxx.in",
    "mobile": "xxxxxxxxx",
    "dealername": "xxx"
},
"sitedetail": {
    "id": "1",
    "name": "xxx",
    "visitorid": "1"
},
"selections": [
    {
        "id": "1",
        "visitorid": "1",
        "siteid": "1",
        "designno": "xxx",
        "qty": "3",
        "roomtype": "xxx",
        "remarks": "xxx"
    },
    {
        "id": "0",
        "visitorid": "1",
        "siteid": "1",
        "designno": "xxx",
        "qty": "3",
        "roomtype": "xxx",
        "remarks": "xxx"
    }
]}

我们将不胜感激高级帮助!

【问题讨论】:

  • 这一切都取决于服务器如何期望它
  • 只是期望使用post方法的多格式数据。
  • multipart 你的意思是?然后将其作为该 multipartbody 的一部分发送
  • 我可以发送,但它是嵌套请求。我不知道如何处理它
  • 我认为您应该将 RequestBody 传递给您的自定义数据。

标签: android retrofit2


【解决方案1】:

我终于解决了这个问题。

如果有人想将带有额外附加参数的图像上传到服务器。以下是方法。

在您的改造 API 请求接口中首先创建方法。

@Multipart
@POST("test/test.post.json")
Call<APIResponseSiteDetails> addImages(@PartMap Map<String, RequestBody> params);

现在您必须在要调用的活动或片段类中调用此方法。

 Map<String, RequestBody> params = new HashMap<>();

if (imageData != null && imageData.size() > 0) {

                        for (int i = 0; i < imageData.size(); i++) {
                            String key = "images[" + i + "]";
                            File file = new File(imageData.get(i).getImageurl());
                            try {
                                File compressedImages = new ImageZipper(AddDetailsActivity.this).compressToFile(file);
                                params.put("" + key + "\"; filename=\"" + file.getName(), getRequestFile(compressedImages));

                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
}

上面的 sn-p 代码仅用于使用 MultiPart 发送图像。现在,如果你想用它发送额外的参数。然后简单地使用它。

params.put("devicetype", toRequestBody(Constants.DEVICE_TYPE)); // This is String request body.

现在,如果您有另一个使用密钥对值的自定义请求并且想要发送单个项目,那么您必须以这种方式进行包装。

public Map<String, RequestBody> getAnotherRequest() {
    Map<String, RequestBody> paStringRequestBodyMap = new HashMap<>();
    paStringRequestBodyMap.put("userid", Functions.toRequestBody("1"));
    paStringRequestBodyMap.put("id", Functions.toRequestBody("1"));
    return paStringRequestBodyMap;
}

现在您必须将其添加到主请求正文中,然后您必须执行。

 for (Map.Entry<String, RequestBody> entry : getAnotherRequest().entrySet()) {
                        String key = entry.getKey();
                        RequestBody value = entry.getValue();
                        params.put("details[" + key + "]", value);
 }

现在,如果你想发送多个请求,那么你需要执行下面的代码,

public Map<String, Map> getContacts() {

    Map<String, Map> paStringRequestBodyMap = new HashMap<>();

    if (showRoomDataList != null && showRoomDataList.size() > 0) {

        for (int i = 0; i < showRoomDataList.size(); i++) {

            Map<String, RequestBody> innnerList = new HashMap<>();
            innnerList.put("id", Functions.toRequestBody("0"));
            innnerList.put("visitorid", Functions.toRequestBody("0"));
            innnerList.put("siteid", Functions.toRequestBody("0"));

            innnerList.put("typeid", Functions.toRequestBody(showRoomDataList.get(i).getTypeid()));
            paStringRequestBodyMap.put(i + "", innnerList);
        }
    }
    return paStringRequestBodyMap;
}

现在把它放到主请求中,

for (Map.Entry<String, Map> entry : getContacts().entrySet()) {

                        String key = entry.getKey();
                        Map value = entry.getValue();

                        Iterator it = value.entrySet().iterator();
                        while (it.hasNext()) {
                            Map.Entry pair = (Map.Entry) it.next();

                            RequestBody requestBody = (RequestBody) pair.getValue();

                            params.put("contacts[" + key + "]" + "[" + pair.getKey() + "]", requestBody);

                            it.remove(); // avoids a ConcurrentModificationException
                        }

                    }

对于图像多部分请求正文

private RequestBody getRequestFile(File file) {

    RequestBody fbody = RequestBody.create(MediaType.parse("image/*"), file);
    return fbody;

}

对于字符串值请求正文

  public static RequestBody toRequestBody(String value) {
  RequestBody body = RequestBody.create(MediaType.parse("text/plain"), value);
  return body;
}

以上是使用带有图像(多部分)数据的密钥对值对单个、多个发布请求执行的代码。我希望这对你们所有人都有帮助。

【讨论】:

    【解决方案2】:

    我认为您应该将 json 作为请求正文发送。为此,您需要 generate 相应 json 的 pojo。那就叫它ReqBody吧,

    // Add header items if required
    @POST("endpoint")
    Call<ResBody> getData(@Body ReqBody body);
    

    另外,将.addConverterFactory(GsonConverterFactory.create()) 添加到您的Retrofit.Builder()

    【讨论】:

      【解决方案3】:

      我认为您遇到了与我几天前相同的问题。您可以在此处找到整个主题以查看我的示例:Is it possible to POST a package of json objects?

      你必须这样做:

      public interface API {
      
        @POST("YOUR_ENDPOINT")
        Call<Post> createPost(@Body PostRequest post);
      }
      

      并创建这个类:

      public class PostRequest {
        final Param1Type param1name;
        final Param2Type param2name; 
      
        PostRequest(Param1Type param1name, Param2Type param2name) {
          this.param1name= param1name;
          this.param2name= param2name;
        }
      }
      

      【讨论】:

      • 那么我也可以使用这个发送包含多部分表单数据的数据吗?
      • 我几天前就是这样做的,效果很好。
      • 你能分享完整的sn-p吗?所以这对我来说很容易
      • sn-p 是什么意思?
      • 我已经检查了你的链接。我关于发送图像的问题。使用 Json 数据我们也不能发送图像文件。
      【解决方案4】:

      你可以试试这个,首先你需要为请求的第一部分创建一个类。所以我会创建这样的东西->

      class Article(
          @field:Json(name = "devicetype") var devicetype: String,
          @field:Json(name = "deviceid") var deviceid: String,
          @field:Json(name = "appversion") var appversion: String,
          @field:Json(name = "apiversion") var apiversion: String,
          @field:Json(name = "timezone") var timezone: String,
          @field:Json(name = "modeltype") var modeltype: String,
          @field:Json(name = "deviceos") var deviceos: String,
          @field:Json(name = "userdeviceid") var userdeviceid: String,
          @field:Json(name = "visitorid") var visitorid: String,
          @field:Json(name = "siteid") var siteid: String,
          @field:Json(name = "visitordetail") var visitordetail: List<VisitorDetail>    //Call the visitordetail class over here like this
      ) : Serializable
      

      然后为“visitordetail”创建一个类文件,像这样->

      class VisitorDetail(
          @field:Json(name = "id") var id: String,
          @field:Json(name = "userid") var userid: String,
          @field:Json(name = "name") var name: String,
          @field:Json(name = "email") var email: String,
          @field:Json(name = "mobile") var mobile: String,
          @field:Json(name = "dealername") var dealername: String,
          @field:Json(name = "sitedetail") var sitedetail: List<SiteDetail>    //Call the site details class over here like this
      ) : Serializable
      

      然后类似地创建一个名为“sitedetail”的类

      class SiteDetail(
          @field:Json(name = "id") var id: String,
          @field:Json(name = "name") var name: String,
          @field:Json(name = "visitorid") var visitorid: String,
          @field:Json(name = "selections") var selections: List<Selections>    //Call the Selections class over here
      ): Serializable
      

      同样做同样的事情,像这样为“选择”创建一个类 ->

      class Selections(
          @field:Json(name = "id") var id: String,
          @field:Json(name = "visitorid") var visitorid: String,
          @field:Json(name = "siteid") var siteid: String,
          @field:Json(name = "designno") var designno: String,
          @field:Json(name = "qty") var qty: String,
          @field:Json(name = "roomtype") var roomtype: String,
          @field:Json(name = "remarks") var remarks: String
      ):Serializable
      

      我在 Kotlin 中做过这个,但你可以在 java 中通过转换来尝试。逻辑是,只要需要调用嵌套请求数据,您只需将所有响应转换为 pojo 类。只需将其一一传递,然后将主 pojo 调用到您的改造中,其余的将由库处理。而且您也可以为多部分执行此操作。 如果有任何愚蠢的错误,比如缺少逗号或其他东西,那么我提前道歉。

      【讨论】:

      • 你能查一下this吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 2020-06-14
      • 2011-12-04
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多