如何在 Android 中使用 HTTPClient 以 JSON 格式发送 POST 请求?

Posted

技术标签:

【中文标题】如何在 Android 中使用 HTTPClient 以 JSON 格式发送 POST 请求?【英文标题】:How to send POST request in JSON using HTTPClient in Android? 【发布时间】:2011-09-07 06:28:57 【问题描述】:

我试图弄清楚如何使用 HTTPClient 从 android POST JSON。我一直试图弄清楚这一点,我在网上找到了很多例子,但我无法让它们中的任何一个起作用。我相信这是因为我缺乏一般的 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();
    
 

【问题讨论】:

也许您可以发布一个您无法使用的示例?通过让某些东西发挥作用,您将了解这些部分是如何组合在一起的。 How to send a JSON object over Request with Android? 的可能重复项 【参考方案1】:

在这个答案中,我使用的是example posted by Justin Grammens。

关于 JSON

JSON 代表 javascript 对象表示法。在 JavaScript 中,属性可以像 object1.nameobject['name']; 一样被引用。文章中的示例使用了这一点 JSON。

零件 以 email 为键、foo@bar.com 为值的粉丝对象


  fan:
    
      email : 'foo@bar.com'
    

所以对象等价物将是fan.email;fan['email'];。两者将具有相同的值 'foo@bar.com'.

关于 HttpClient 请求

以下是我们作者用来制作HttpClient Request的内容。我并没有声称自己是这方面的专家,所以如果有人有更好的方式来表达一些术语,请随意。

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 reference。简而言之,映射类似于字典或哈希。

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;

请随时对关于这篇文章的任何问题发表评论,或者如果我没有说清楚,或者如果我没有触及你仍然困惑的东西......等等,无论你真的想到了什么。

(如果 Justin Grammens 不同意,我会删除。但如果不同意,那么感谢 Justin 的冷静。)

更新

我刚好得到一个关于如何使用代码的评论,并意识到返回类型有错误。 方法签名被设置为返回一个字符串,但在这种情况下它没有返回任何东西。我改了签名 到 HttpResponse,并将在Getting Response Body of HttpResponse 上将您转至此链接 路径变量是 url,我更新以修复代码中的错误。

【讨论】:

谢谢@Terrance。因此,在另一个类中,他正在创建一个具有不同键和值的映射,这些键和值稍后将转换为 JSONObjects。我尝试实现类似的东西,但我也没有地图经验,我会将我尝试实现的代码添加到我的原始帖子中。您对此后发生的事情的解释,我成功地通过创建具有硬编码名称和值的 JSONObjects 使其工作。谢谢! 贾斯汀说他同意。他现在应该有足够的代表来自己发表评论了。 我想使用这个代码。我该怎么做?请指定什么是路径变量以及必须返回什么,以便在我的 java 端我可以获取数据。 路径变量是url,最后一行的Response如何处理的细节在这里。 thinkandroid.wordpress.com/2009/12/30/… 没有理由 getJsonObjectFromMap(): JSONObject 有一个构造函数接受Map: developer.android.com/reference/org/json/…【参考方案2】:

这是@Terrance 答案的替代解决方案。您可以轻松地将转换外包。 Gson library 在将各种数据结构转换为 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;

使用Jackson 代替 Gson 可以完成类似的操作。我还建议查看Retrofit,它为您隐藏了很多样板代码。对于更有经验的开发人员,我建议尝试RxAndroid。

【讨论】:

我的应用程序正在通过 HttpPut 方法发送数据。当服务器收到请求时,它以 json 数据的形式回复。我不知道如何从 json 获取数据。请告诉我。 CODE. @kongkea 请查看GSON library。它能够将 JSON 文件解析为 Java 对象。 @JJD 到目前为止,您的建议是将数据发送到远程服务器,这是一个很好的解释,但想知道如何使用 HTTP 协议解析 JSON 对象。你也可以用 JSON 解析来详细说明你的答案吗?这对每个新手都会很有帮助。 @AndroidDev 请打开一个新问题,因为这个问题是关于从客户端向服务器发送数据的。随意在这里放一个链接。 @JJD 你正在调用抽象方法execute() 当然失败了【参考方案3】:

我建议使用 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();
 

【讨论】:

【参考方案4】:

这个任务的代码太多,检查这个库https://github.com/kodart/Httpzoid 它在内部使用 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 支持:/【参考方案5】:

有几种方法可以建立 HHTP 连接并从 RESTFULL Web 服务获取数据。最近的一个是 GSON。但是在继续使用 GSON 之前,您必须对创建 HTTP 客户端并与远程服务器执行数据通信的最传统方式有所了解。我已经提到了使用 HTTPClient 发送 POST 和 GET 请求的两种方法。

/**
 * 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;

【讨论】:

以上是关于如何在 Android 中使用 HTTPClient 以 JSON 格式发送 POST 请求?的主要内容,如果未能解决你的问题,请参考以下文章

HttpClien高并发请求连接池 - PoolingHttpClientConnectionManager

Android 错误:MultipartEntity,客户端发送的请求在语法上不正确

使用eclipse阅读java源码

如何将此 .NET RestSharp 代码转换为 Microsoft.Net.Http HttpClient 代码?

通用 Windows 项目 - HttpClient 异常

使用 Gradle 在运行时出现 NoClassDefFoundError