Как отправить запрос POST в JSON с помощью HTTPClient в Android?

111

Я пытаюсь понять, как отправить JSON с Android на POST с помощью HTTPClient. Я пытался понять это некоторое время, я нашел множество примеров в Интернете, но я не могу заставить ни один из них работать. Я считаю, что это связано с отсутствием у меня знаний о JSON / сетях в целом. Я знаю, что существует множество примеров, но может ли кто-нибудь указать мне на настоящий учебник? Я ищу пошаговый процесс с кодом и объяснением, почему вы делаете каждый шаг или что делает этот шаг. Это не должно быть сложным, достаточно простого.

Опять же, я знаю, что существует масса примеров, я просто действительно ищу пример с объяснением того, что именно происходит и почему это происходит именно так.

Если кто-то знает об этой хорошей книге для Android, дайте мне знать.

Еще раз спасибо за помощь @terrance, вот код, который я описал ниже

public void shNameVerParams() throws Exception{
     String path = //removed
     HashMap  params = new HashMap();

     params.put(new String("Name"), "Value"); 
     params.put(new String("Name"), "Value");

     try {
        HttpClient.SendHttpPost(path, params);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }
Гаурав Ганди
источник
Возможно, вы можете опубликовать один из примеров, который у вас не получается? Получив что-то работающее, вы узнаете, как эти части подходят друг другу.
fredw 02

Ответы:

157

В этом ответе я использую пример, опубликованный Джастином Грамменсом. .

О JSON

JSON расшифровывается как JavaScript Object Notation. В свойствах JavaScript можно ссылаться как на это, так object1.nameи на это object['name']; . В примере из статьи используется этот бит JSON.

Части
Фан-объект с электронной почтой в качестве ключа и foo@bar.com в качестве значения

{
  fan:
    {
      email : 'foo@bar.com'
    }
}

Таким образом, эквивалент объекта будет fan.email;или fan['email'];. Оба будут иметь одинаковое значение'foo@bar.com' .

О запросе HttpClient

Ниже приводится то, что наш автор использовал для создания запроса HttpClient . Я вовсе не претендую на звание эксперта в этом вопросе, поэтому, если у кого-то есть лучший способ сформулировать некоторые термины, не стесняйтесь.

public static HttpResponse makeRequest(String path, Map params) throws Exception 
{
    //instantiates httpclient to make request
    DefaultHttpClient httpclient = new DefaultHttpClient();

    //url with the post data
    HttpPost httpost = new HttpPost(path);

    //convert parameters into JSON object
    JSONObject holder = getJsonObjectFromMap(params);

    //passes the results to a string builder/entity
    StringEntity se = new StringEntity(holder.toString());

    //sets the post request as the resulting string
    httpost.setEntity(se);
    //sets a request header so the page receving the request
    //will know what to do with it
    httpost.setHeader("Accept", "application/json");
    httpost.setHeader("Content-type", "application/json");

    //Handles what is returned from the page 
    ResponseHandler responseHandler = new BasicResponseHandler();
    return httpclient.execute(httpost, responseHandler);
}

карта

Если вы не знакомы со Mapструктурой данных, взгляните на справочник Java Map . Короче говоря, карта похожа на словарь или хеш.

private static JSONObject getJsonObjectFromMap(Map params) throws JSONException {

    //all the passed parameters from the post request
    //iterator used to loop through all the parameters
    //passed in the post request
    Iterator iter = params.entrySet().iterator();

    //Stores JSON
    JSONObject holder = new JSONObject();

    //using the earlier example your first entry would get email
    //and the inner while would get the value which would be 'foo@bar.com' 
    //{ fan: { email : 'foo@bar.com' } }

    //While there is another entry
    while (iter.hasNext()) 
    {
        //gets an entry in the params
        Map.Entry pairs = (Map.Entry)iter.next();

        //creates a key for Map
        String key = (String)pairs.getKey();

        //Create a new map
        Map m = (Map)pairs.getValue();   

        //object for storing Json
        JSONObject data = new JSONObject();

        //gets the value
        Iterator iter2 = m.entrySet().iterator();
        while (iter2.hasNext()) 
        {
            Map.Entry pairs2 = (Map.Entry)iter2.next();
            data.put((String)pairs2.getKey(), (String)pairs2.getValue());
        }

        //puts email and 'foo@bar.com'  together in map
        holder.put(key, data);
    }
    return holder;
}

Пожалуйста, не стесняйтесь комментировать любые вопросы, которые возникают по поводу этого поста, или если я что-то не прояснил, или если я не коснулся того, что вас все еще смущает ...

(Я сниму, если Джастин Грэмменс не одобрит. Но если нет, то спасибо Джастину за то, что он к этому относится.)

Обновить

Я просто случайно получил комментарий о том, как использовать код, и понял, что в возвращаемом типе есть ошибка. Сигнатура метода была настроена на возврат строки, но в данном случае она ничего не возвращала. Я изменил подпись на HttpResponse и отсылаю вас к этой ссылке « Получение тела ответа HttpResponse», переменная пути - это URL-адрес, и я обновился, чтобы исправить ошибку в коде.

Терренс
источник
Спасибо @Terrance. Итак, в другом классе он создает карту с разными ключами и значениями, которые позже будут преобразованы в JSONObjects. Я пробовал реализовать нечто подобное, но у меня тоже нет опыта работы с картами, я добавлю код того, что пытался реализовать, в свой исходный пост. Ваши объяснения того, что происходит с тех пор, были сделаны с тех пор, и мне удалось заставить это работать, создав JSONObjects с жестко запрограммированными именами и значениями. Спасибо!
Уут, рад, что смог помочь.
Terrance
Джастин говорит, что одобряет. У него уже должно быть достаточно представителей, чтобы прийти и оставить комментарий.
Abizern 03
Я хочу использовать этот код. Как мне это сделать? Пожалуйста, укажите, что такое переменная пути и что должно быть возвращено, чтобы на моем конце java я мог получить данные.
Prateek
3
Нет причин для getJsonObjectFromMap(): JSONObject имеет конструктор, который принимает Map: developer.android.com/reference/org/json/…
pr1001
41

Вот альтернативное решение ответа @Terrance. Вы можете легко передать конверсию на аутсорсинг. Библиотека Gson отлично справляется с преобразованием различных структур данных в JSON и наоборот.

public static void execute() {
    Map<String, String> comment = new HashMap<String, String>();
    comment.put("subject", "Using the GSON library");
    comment.put("message", "Using libraries is convenient.");
    String json = new GsonBuilder().create().toJson(comment, Map.class);
    makeRequest("http://192.168.0.1:3000/post/77/comments", json);
}

public static HttpResponse makeRequest(String uri, String json) {
    try {
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(json));
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");
        return new DefaultHttpClient().execute(httpPost);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Аналогичное можно сделать, используя Джексона вместо Джексона. Я также рекомендую взглянуть на Retrofit, который скрывает для вас большую часть этого шаблонного кода. Более опытным разработчикам я рекомендую попробовать RxAndroid .

JJD
источник
мое приложение отправляет данные через метод HttpPut. когда сервер получил запрос, он отвечает как данные json. Я не знаю, как получить данные из json. Скажите мне, пожалуйста. КОД .
kongkea
@kongkea Пожалуйста, загляните в библиотеку GSON . Он способен анализировать файл JSON на объекты Java.
JJD
@JJD Пока что вы предлагаете отправить данные на удаленный сервер и это хорошее объяснение, но вы хотите знать, как анализировать объект JSON с использованием протокола HTTP. Можете ли вы уточнить свой ответ с помощью анализа JSON. Будет очень полезно для всех, кто в этом новичок.
AndroidDev
@AndroidDev Пожалуйста, откройте новый вопрос, так как этот вопрос касается отправки данных с клиента на сервер. Не стесняйтесь оставлять ссылку здесь.
JJD
@JJD, вы вызываете абстрактный метод, execute()и он, конечно же, не работает
Константин Конопко
33

Я рекомендую использовать это HttpURLConnectionвместо этого HttpGet. Как HttpGetуже не рекомендуется в Android API уровня 22.

HttpURLConnection httpcon;  
String url = null;
String data = null;
String result = null;
try {
  //Connect
  httpcon = (HttpURLConnection) ((new URL (url).openConnection()));
  httpcon.setDoOutput(true);
  httpcon.setRequestProperty("Content-Type", "application/json");
  httpcon.setRequestProperty("Accept", "application/json");
  httpcon.setRequestMethod("POST");
  httpcon.connect();

  //Write       
  OutputStream os = httpcon.getOutputStream();
  BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
  writer.write(data);
  writer.close();
  os.close();

  //Read        
  BufferedReader br = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"UTF-8"));

  String line = null; 
  StringBuilder sb = new StringBuilder();         

  while ((line = br.readLine()) != null) {  
    sb.append(line); 
  }         

  br.close();  
  result = sb.toString();

} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} 
Эгис
источник
5

Слишком много кода для этой задачи, проверьте эту библиотеку https://github.com/kodart/Httpzoid. Is использует GSON внутренне и предоставляет API, который работает с объектами. Все детали JSON скрыты.

Http http = HttpFactory.create(context);
http.get("http://example.com/users")
    .handler(new ResponseHandler<User[]>() {
        @Override
        public void success(User[] users, HttpResponse response) {
        }
    }).execute();
Артур
источник
отличное решение, к сожалению, в этом плагине отсутствует поддержка Gradle: /
electronicix384128
3

Есть несколько способов установить соединение HHTP и получить данные из веб-службы RESTFULL. Самый последний - GSON. Но прежде чем перейти к GSON, вы должны иметь некоторое представление о наиболее традиционном способе создания HTTP-клиента и выполнения обмена данными с удаленным сервером. Я упомянул оба метода для отправки запросов POST и GET с использованием HTTPClient.

/**
 * This method is used to process GET requests to the server.
 * 
 * @param url 
 * @return String
 * @throws IOException
 */
public static String connect(String url) throws IOException {

    HttpGet httpget = new HttpGet(url);
    HttpResponse response;
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used. 
    int timeoutConnection = 60*1000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 60*1000;

    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    try {

        response = httpclient.execute(httpget);

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            result = convertStreamToString(instream);
            //instream.close();
        }
    } 
    catch (ClientProtocolException e) {
        Utilities.showDLog("connect","ClientProtocolException:-"+e);
    } catch (IOException e) {
        Utilities.showDLog("connect","IOException:-"+e); 
    }
    return result;
}


 /**
 * This method is used to send POST requests to the server.
 * 
 * @param URL
 * @param paramenter
 * @return result of server response
 */
static public String postHTPPRequest(String URL, String paramenter) {       

    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used. 
    int timeoutConnection = 60*1000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 60*1000;

    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    HttpPost httppost = new HttpPost(URL);
    httppost.setHeader("Content-Type", "application/json");
    try {
        if (paramenter != null) {
            StringEntity tmp = null;
            tmp = new StringEntity(paramenter, "UTF-8");
            httppost.setEntity(tmp);
        }
        HttpResponse httpResponse = null;
        httpResponse = httpclient.execute(httppost);
        HttpEntity entity = httpResponse.getEntity();
        if (entity != null) {
            InputStream input = null;
            input = entity.getContent();
            String res = convertStreamToString(input);
            return res;
        }
    } 
     catch (Exception e) {
        System.out.print(e.toString());
    }
    return null;
}
Майк Кларк
источник