HttpURLConnection从网上获取Json数据并解析
1、HttpURLConnection请求数据的步骤
(1)构造一个URL接口地址:
URL url = new URL(“httpurl”);
(2)用URL来创建一个连接:
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
(3)设置请求方式(get/put):
conn.setRequestMethod(“GET”)
(4)设置需要的头设定(下面是申请天气预报服务的例子):
conn.setRequestProperty(“apikey”,”你自己的apikey”)
(5)连接:
conn.connect()
到这里为止就已经连上了网络提供的接口地址。这里的setRequestProperty()需要讲解下。
2、setRequestProperty浅谈
作用:告诉服务器你需要的服务。如编码、请求数据方式、是否使用缓存等等,用这个方法告诉服务器,然后服务器才会尽量按照你的要求给你传输数据,如果什么都不设置,服务器就按缺省配置传递内容给你[1]。
SetRequestProperty的参数是key-value的形式,它是作为http的头部设定。http协议采用的是请求/响应模型,浏览器或客户端发出请求,服务器给与响应。就整个网络资源传输而言,包括message-header和message-body两部分。首先传递message-header,即http header消息。http header消息通常被分为4个部分:general header,request header,response header, entity header。但是这种分法就理解而言,感觉界限不太明确。根据维基百科对http header内容的组织形式,大体分为Request和Response两部分[2-3]。
Request部分
Header |
解释 |
示例 |
Accept |
指定客户端能够接收的内容类型 |
Accept: text/plain, text/html |
Accept-Charset |
浏览器可以接受的字符编码集。 |
Accept-Charset: iso-8859-5 |
Accept-Encoding |
指定浏览器可以支持的web服务器返回内容压缩编码类型。 |
Accept-Encoding: compress, gzip |
Accept-Language |
浏览器可接受的语言 |
Accept-Language: en,zh |
Accept-Ranges |
可以请求网页实体的一个或者多个子范围字段 |
Accept-Ranges: bytes |
Authorization |
HTTP授权的授权证书 |
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control |
指定请求和响应遵循的缓存机制 |
Cache-Control: no-cache |
Connection |
表示是否需要持久连接。(HTTP 1.1默认进行持久连接) |
Connection: close |
Cookie |
HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 |
Cookie: $Version=1; Skin=new; |
Content-Length |
请求的内容长度 |
Content-Length: 348 |
Content-Type |
请求的与实体对应的MIME信息 |
Content-Type: application/x-www-form-urlencoded |
Date |
请求发送的日期和时间 |
Date: Tue, 15 Nov 2010 08:12:31 GMT |
Expect |
请求的特定的服务器行为 |
Expect: 100-continue |
From |
发出请求的用户的Email |
From: user@email.com |
Host |
指定请求的服务器的域名和端口号 |
Host: www.zcmhi.com |
If-Match |
只有请求内容与实体相匹配才有效 |
If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since |
如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 |
If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
If-None-Match |
如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 |
If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range |
如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag |
If-Range: “737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since |
只在实体在指定时间之后未被修改才请求成功 |
If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
Max-Forwards |
限制信息通过代理和网关传送的时间 |
Max-Forwards: 10 |
Pragma |
用来包含实现特定的指令 |
Pragma: no-cache |
Proxy-Authorization |
连接到代理的授权证书 |
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range |
只请求实体的一部分,指定范围 |
Range: bytes=500-999 |
Referer |
先前网页的地址,当前请求网页紧随其后,即来路 |
Referer: http://www.zcmhi.com/archives/71.html |
TE |
客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 |
TE: trailers,deflate;q=0.5 |
Upgrade |
向服务器指定某种传输协议以便服务器进行转换(如果支持) |
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent |
User-Agent的内容包含发出请求的用户信息 |
User-Agent: Mozilla/5.0 (Linux; X11) |
Via |
通知中间网关或代理服务器地址,通信协议 |
Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning |
关于消息实体的警告信息 |
Warn: 199 Miscellaneous warning |
当然,http的头设置也可以自定义的,但要符合该网站的要求,如做天气预报在APIStore申请天气预报接口时的头设置connection.setRequestProperty("apikey", "你的apikey")。
注意事项:这个方法要在建立连接之前调用,即调用connect()方法之前。但connect方法可以不用明确调用,因为在调用getInputStream()方法时会检查连接是否已经建立,如果没有建立,则会调用connect()方法[4]。
3 代码
以下是HttpURLConnection获取数据的代码,是APIStore天气预报API里提供的示例代码
public static String request(String httpUrl, String httpArg) { BufferedReader reader = null; String result = null; StringBuffer sbf = new StringBuffer(); httpUrl = httpUrl + "?" + httpArg; try { URL url = new URL(httpUrl); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setRequestMethod("GET"); /**setRequestProperty(key,value) * Sets the general request property. If a property with the key already * exists, overwrite its value with the new value. * 设置通用的请求属性。如果该key对应的的属性值已经存在,那么新值将覆盖以前的值 * <p> NOTE: HTTP requires all request properties which can * legally have multiple instances with the same key * to use a comma-seperated list syntax which enables multiple * properties to be appended into a single property. *提示:HTTP要求拥有相同key值的多个实例的所有请求属性,可以使用逗号分隔的列表语法,这样就可以将多个属性附加到单个属性中 * @param key the keyword by which the request is known * (e.g., "<code>Accept</code>"). * @param value the value associated with it. * @throws IllegalStateException if already connected * @throws NullPointerException if key is <CODE>null</CODE> * @see #getRequestProperty(java.lang.String) */ connection.setRequestProperty("apikey", "71e4b699*********cf44ebb02cd2"); connection.connect(); InputStream is = connection.getInputStream(); reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); String strRead = null; while ((strRead = reader.readLine()) != null) { sbf.append(strRead); sbf.append(" "); } reader.close(); result = sbf.toString(); } catch (Exception e) { e.printStackTrace(); } return result; }
Json解析
这里用的Json解析用的并不是Android平台自己自带的,而是网上下载的json-lib-2.4-jdk15.jar[5](导入的是net.sf.json.*下的类)包和一些其它的公用包。
String httpUrl = "http://apis.baidu.com/heweather/weather/free"; String httpArg = "city=wuhan"; String jsonResult = request(httpUrl, httpArg); JSONObject obj = JSONObject.fromObject(jsonResult); String result = obj.getString("HeWeather data service 3.0"); JSONArray arr = JSONArray.fromObject(result); obj = arr.getJSONObject(0); result = obj.getString("now");
以上是解析两次后的代码,得到的数据里面当然还包含json格式的数据,如果想要得到更深层次的内容,就继续解析即可。
参考内容:
[1] https://zhidao.baidu.com/question/504154973.html
[2] http://kb.cnblogs.com/page/92320/
[3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
[4] http://blog.csdn.net/nuccch/article/details/23399107
[5] http://download.csdn.net/detail/hacker13a/7544797