Как передать сложный параметр в запрос POST с помощью HTTP-клиента Apache?

Я пытаюсь отправить POST запрос с таким телом

{
  "method": "getAreas",
  "methodProperties": {
      "prop1" : "value1",
      "prop2" : "value2",
   }
}

Вот мой код

static final String HOST = "https://somehost.com";

  public String sendPost(String method,
      Map<String, String> methodProperties) throws ClientProtocolException, IOException {

    HttpPost post = new HttpPost(HOST);

    List<NameValuePair> urlParameters = new ArrayList<>();
    urlParameters.add(new BasicNameValuePair("method", method));

    List<NameValuePair> methodPropertiesList = methodProperties.entrySet().stream()
                .map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());

    // ??? urlParameters.add(new BasicNameValuePair("methodProperties", methodPropertiesList));

    post.setEntity(new UrlEncodedFormEntity(urlParameters));

    try (CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(post)) {

      return EntityUtils.toString(response.getEntity());
    }
  }

Но конструктор BasicNameValuePair применяет (String, String). Поэтому мне нужен другой класс.

Есть ли способ добавить methodPropertiesList к urlParameters?


person alex valuiskyi    schedule 31.10.2019    source источник


Ответы (3)


ваш запрос выглядит как структура json, поэтому отправьте данные, как показано ниже:

 class pojo1{
   String method;
   Map<String,String> methodProperties;
 }

String postUrl = "www.site.com";// put in your url
Gson gson = new Gson();
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postUrl);
StringEntity postingString = new StringEntity(gson.toJson(pojo1));//gson.tojson()    converts your pojo to json
post.setEntity(postingString);
post.setHeader("Content-type", "application/json");
HttpResponse  response = httpClient.execute(post);

ref:HTTP POST с использованием JSON в Java

person Sushil Mittal    schedule 31.10.2019

Существует известный подход к этой проблеме. В большинстве случаев вы будете создавать свой собственный объект, описывающий то, что вы хотите отправить в HttpPost. Итак, у вас будет что-то вроде:

static final String HOST = "https://somehost.com";

  public String sendPost(String method,
      Map<String, String> methodProperties) throws ClientProtocolException, IOException {

    HttpPost post = new HttpPost(HOST);
    MyResource resource = new MyResource();
    resource.setMethod(method);
    MyNestedResource nestedResource = new MyNestedResource();
    nestedResource.setMethodProperties(methodProperties);
    resource.setNestedResourceMethodProperties(nestedResource);

    StringEntity strEntity = new StringEntity(gson.toJson(resource));
    post.setEntity(strEntity);

    try (CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(post)) {

      return EntityUtils.toString(response.getEntity());
    }
  }

И обычно именно так вы подходите к более сложным объектам json с вложенной структурой. Вы должны создать классы для ресурсов, которые вы хотите отправить (в вашем примере это может быть один класс и использовать в нем карту, но обычно вы создаете класс и для вложенного объекта, если он имеет определенную структуру). Чтобы лучше ознакомиться со всей картиной, лучше ознакомьтесь с этим руководством: https://www.baeldung.com/jackson-mapping-dynamic-object

person saferJo    schedule 31.10.2019
comment
Я понимаю ход твоих мыслей, но у setEntity такая подпись (org.apache.http.HttpEntity entity). Чтобы реализовать HttpEntity, мне нужно реализовать кучу методов - person alex valuiskyi; 31.10.2019
comment
да, извините, вы можете использовать это: StringEntity strEntity= new StringEntity(gson.toJson(resource)); Я тоже отредактирую свой ответ. - person saferJo; 01.11.2019

Используя ответ Sushil Mittal, вот мое решение

static final String HOST = "https://somehost.com";

  public String sendPost(String method, Map<String, String> methodProperties) throws ClientProtocolException, IOException {

    HttpPost post = new HttpPost(HOST);  
    Gson gson = new Gson();

    Params params = new Params(method, methodProperties);
    StringEntity entity = new StringEntity(gson.toJson(params));   
    post.setEntity(entity);

    try (CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(post)) {

      return EntityUtils.toString(response.getEntity());
    }
  }

  class Params {

    String method;   
    Map<String, String> methodProperties;

    public Params(String method, Map<String, String> methodProperties) {
      this.method = method;
      this.methodProperties = methodProperties;
    }

    //getters
  }
person alex valuiskyi    schedule 31.10.2019