GVKun编程网logo

jsonp技术访问天气Demo(嘲笑鸡儿小)

20

对于jsonp技术访问天气Demo感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍嘲笑鸡儿小,并为您提供关于@CosmosInput无法识别json的JsonProperty、ajax小demo

对于jsonp技术访问天气Demo感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍嘲笑鸡儿小,并为您提供关于@CosmosInput 无法识别 json 的 JsonProperty、ajax小demo---JSONP 跨域原理及简单应用、AJAX(七)jsonp实战--天气预报、Android-天气预报Demo-JSON数据解析的有用信息。

本文目录一览:

jsonp技术访问天气Demo(嘲笑鸡儿小)

jsonp技术访问天气Demo(嘲笑鸡儿小)

jsonp技术访问天气Demo,该网站实现了返回数据为xml或json类型

注意:select*fromjsonwhereurl='..'要用空格隔开

http://query.yahooapis.com/v1/public/yql?q=select*fromjsonwhereurl='http://m.weather.com.cn/data/101010100.html'
//返回一个xml的文档树(object类型)

http://query.yahooapis.com/v1/public/yql?q=select*fromjsonwhereurl='http://m.weather.com.cn/data/101010100.html'&format=json
//将返回的xml的文档树(object类型)转变为json类型(object)


tianqi.jsp代码如下:

<%@pagepageEncoding="utf-8"%>
<%@tagliburi="/struts-tags"prefix="s"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>注册</title>
<Metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/>
<scripttype="text/javascript"src="../js/jquery-1.4.3.js"></script>
</head>

<body>
<fontcolor='red'>天气预报demo界面</font>

<divid="content">
文本框内容

</div>
<script>
$(function(){
$.getJSON("http://query.yahooapis.com/v1/public/yql",

{q:"select*fromjsonwhereurl='http://m.weather.com.cn/data/101010100.html'",format:"json"},

function(data){var$content=$("#content")if(data.query.results){varresult=JSON.stringify(data.query.results);$content.text(result);varobj=eval('('+result+')');alert(obj.weatherinfo.city);}else{$content.text('nosuchcode:'+code);}});});</script></body><script></script></html>

@CosmosInput 无法识别 json 的 JsonProperty

@CosmosInput 无法识别 json 的 JsonProperty

如何解决@CosmosInput 无法识别 json 的 JsonProperty?

下午好:

我目前正在创建一个带有 @CosmosInput 的 Azure 函数。我有这些豆子:

public class Product {
    private String id;
    @JsonAlias("Name1")
    private String name;
    private Tipo tipo;

    // get y set
}

public class Type1 {
    private String id;
    @JsonAlias("Name2")
    private String name;

    public String getId() {
        return id;
    }
}

我在 MongoDB 或 CosmosDB 中的对象:

{
    "id": "1","Name1": "Product 1","tipo": {
        "id": "T1","Name2": "Type 1"
    }
}

但是当我运行该函数时,它无法识别对象“Name1”和“Name2”。功能是这样的:

@FunctionName("example")
public String run(@TimerTrigger(name = "clock",schedule = "expression") String clock,@CosmosDBInput(name = "items",databaseName = "example",collectionName = "Product",connectionStringSetting = "connectionZ") Optional<List<Product>> products
        final ExecutionContext context) {
            for(Product p: products.get()){
                System.out.println("Name: " + p.getName());
            }
            
}

字段“名称”给我带来了空值。

拜托,我不知道你能不能告诉我可能遗漏了什么。

谢谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

ajax小demo---JSONP 跨域原理及简单应用

ajax小demo---JSONP 跨域原理及简单应用

一.jsonp

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

因为同源策略,(它是由netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。)我们不能从不同的域(网站)访问数据,而jsonp就是用来实现这种不能跨域请求数据。

二.jsonp原理:

在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,但img、iframe、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。然而,JSONP就是通过script节点src属性来实现调用跨域的请求。通过动态的创建script标签,当我们通过JSONP模式请求跨域资源时,服务器返回给客户端一段javascript代码,这段javascript代码自动调用客户端回调函数。

三.实例

当使用ajax本地调用url='http://127.0.0.1/ajax/json/test.php?data='+jsonobj+"&r="+Math.random();会出现下面的错误:不能跨域请求

wKioL1cnKOPhEyL2AACekYRLi0M855.jpg

然而,

使用jsonp就可以解决这个问题:具体代码如下:

<script>
	varresult=false;	
		functioncheck(){
			if(resultform()){
				returntrue;
			}
			else{
				returnfalse;
			}
		}
functioncheckform(){
varusernameobj=document.getElementById('username').value;
varusernumobj=document.getElementById('usernum').value;
vardata={username:usernameobj,usernum:usernumobj};
	varjsonobj=JSON.stringify(data);
url='http://127.0.0.1/ajax/json/test.PHP?data='+jsonobj+"&r="+Math.random()+"&callbackname=jp";
//动态添加script标签
	varscripttag=document.createElement("script");
scripttag.setAttribute("src",url);
document.body.appendChild(scripttag);


}
//客户端回调函数
varjp=function(data){
vartips=document.getElementById('tips');
if(data['username']=="11"){
		tips.innerHTML="<h1>你输入的名字是:"+data['username']+"</h1>";
		result=true;
	}
else{
		tips.innerHTML="<h1>你输入的有误</h1>";
			result=false;
			}

resultform();

			}

functionresultform(){
	if(result){
		returntrue;
	}
	else{
		alert("您输入的有误");
		returnfalse;
	}
}
	</script>
PHP页面代码:
<?PHP
$data=json_decode($_GET['data'],true);
$callbackname=$_GET['callbackname'];
echo$callbackname."(".json_encode($data).")";
?>

效果图:

wKioL1cnK1ywa1muAACt0YidnvM032.jpg

AJAX(七)jsonp实战--天气预报

AJAX(七)jsonp实战--天气预报

  一、案例

  本次要做的案例的是使用jsonp制作一个查询天气情况的网页,我会从如何抓取数据接口,到一步一步完成这个案例来详细讲解。

  这个页面样式非常简单,截图如下。用户需要先选择一个城市,然后点击查看天气,那么最近5天的天气数据,就会展示到下面。

  

分享图片

 

  二、数据从何而来

  当然我们不可能自己建气象站,我们只有通过互联网拿到别人“分享”给我们的数据接口,然后通过这个数据接口获取全国的气象数据。这样我们就必须使用jsonp了,因为提供气象数据服务的api,其所在的域名肯定跟我们自己的应用程序不是一个域名。

  那么问题来了,我们如何知道哪里有api提供气象数据服务的?这个就要多观察多积累了。比如现在很多人的电脑上都会安装360,一般360杀毒在安装时候会篡改你的浏览器主页为“hao360”这个网站,那么你打开网页,每次都会看到这样的画面。

                  

分享图片

 

  这个网站在非常显眼的地方提供了一个查看天气的模块。难道360还开着气象站?如果不是,那我们只要看看它是如何搞到数据的,我们就能如法炮制了。

  一般你可以这样做:

  1.在气象模块上点鼠标右键->审查元素。去看看他的结构

  2.打开开发者选项工具窗口,点击Network(网络)选项卡,然后去查看请求报文,这样就能找到气象数据从哪儿来了。

  不过,如果你没有经验,你会被请求报文列表中的数据给吓住,因为实在是太多了,至少不下300条请求项。那我们怎么去找真正需要的那个请求呢?

  试想,这个hao360也不可能自己弄个气象站,所以它必然也是抓取的第三方api,所以也必然是通过jsonp的形式来实现的。那么我们只需要在所有的请求报文中按type这一列排下序,然后就只管看请求类型是script的那些项。这样一下就把范围缩小了很多很多。

  最后我们找到,这里的请求url是:https://cdn.weather.hao.360.cn/sed_api_weather_info.php?code=101180201&app=hao360&_jsonp=__jsonp3__

  简单说明下这个url的参数

  1.code:要查询的城市编码,这个可以百度

  2._jsonp:你自己定义的回调函数的名字。

  3.其他的参数都无关紧要,至少对本案例来说是这样。

  在浏览器里打开这个链接,你看到的结果是这样的:

分享图片

  当然,我只截取了一小部分。不过已经可以看出了,这是一个典型的jsonp跨域访问。

  然后,我把数据copy出来,贴到sublime中,格式化之后,数据是这个样子的。

 1 {
 2     "pubdate": "2018-06-25", 3     "pubtime": "16:44:10", 4     "time": 1529916250, 5     "area": [
 6         ["\u6cb3\u5357","18"], 7         ["\u5b89\u9633","1802"], 8         ["\u5b89\u9633","101180201"]
 9     ],10     "weather": [{
11         "date": "2018-06-25",12         "info": {
13             "dawn": ["2","\u9634","24","\u5357\u98ce","\u5fae\u98ce","19:44"],14             "day": ["8","\u4e2d\u96e8","27","\u5317\u98ce","05:07"],15             "night": ["8","22","\u897f\u98ce","19:44"]
16         }
17     },{
18         "date": "2018-06-26",19         "info": {
20             "dawn": ["8",21             "day": ["7","\u5c0f\u96e8","28",22             "night": ["1","\u591a\u4e91","19:44"]
23         }
24     },{
25         "date": "2018-06-27",26         "info": {
27             "dawn": ["1",28             "day": ["0","\u6674","37","05:08"],29             "night": ["0","3-5\u7ea7","19:44"]
30         }
31     },{
32         "date": "2018-06-28",33         "info": {
34             "dawn": ["0",35             "day": ["0","36","\u4e1c\u5317\u98ce",36             "night": ["1","21","19:45"]
37         }
38     },{
39         "date": "2018-06-29",40         "info": {
41             "dawn": ["1","19:45"],42             "day": ["1","35","\u4e1c\u5357\u98ce",43             "night": ["1","19:45"]
44         }
45     }],
46     。。。。。。
47 }

  简单解释下数据:

  1.这里只截取了数据的一部分,只保留了我们案例中需要用到的那一小部分,感兴趣的自己去研究吧。

  2.显然,这个数据是js中的,json格式数据。

  3.本案例中用到的气象数据,是在这个json对象的“weather”属性中。这个属性的值是一个js数组,数组一共有5个元素,每个元素又是一个json对象,每个json对象都代表了一天的天气情况。

  三、案例的HTML结构

  先看下页面的HTML结构  

<!DOCTYPE html>
<html lang="en">
<head>
    <Meta charset="UTF-8">
    <Meta name="viewport" content="width=device-width,initial-scale=1.0">
    <Meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>天气预报-hao360接口</title>
    <link rel="stylesheet" href="css/weather.css">
</head>
<body>
    <div class="wt_container">
        <div class="city">
            <select id="selCity">
                <option value="101180201">大安阳</option>
                <option value="101010100">北京</option>
                <option value="101180101">郑州</option>
                <option value="101250101">长沙</option>
                <option value="101050101">哈尔滨</option>
                <option value="101130101">乌鲁木齐</option>
                <option value="101280101">广州</option>
            </select>
            <button id="btn">查看天气</button>
        </div>
        <div class="weather">
            <ul id="wtInfo">
                <!-- <li>
                    <h2>25日</h2>
                    <div>
                        <h3>白天天气</h3>
                        <p>天气:</p>
                        <p>温度</p>
                        <p>风向</p>
                        <p>风速</p>
                    </div>
                    <div>
                        <h3>夜间天气</h3>
                        <p>天气:</p>
                        <p>温度</p>
                        <p>风向</p>
                        <p>风速</p>
                    </div>
                </li>                 -->
            </ul>
        </div>
    </div>
</body>
</html>

  大家都看得懂,简单说明下:

  1.select标签中的每个选项都有一个value值,这个值对应的城市编码,这个编码是国家标准编码,不是自己随便乱写的,我是从百度出来然后写死到页面上的。当然,网上也有关于提供省市编码查询的api,你完全可以根据本案例所讲的方法,结合之前AJAX中讲的省市联动的案例,把这里城市的选择做成活的。我这里为了简单起见,随便从网上扒了几个城市,把城市的code拷贝了一下就写死到HTML了。目的只是为了让例子别太复杂。

  2.由于我们拿到的数据是5天的数据,所以我们用一个<ul id = "wtInof">标签来展示所有的查询到的5天的天气,每天的天气用一个li包住。HTML中注释掉的部分就是模拟数据。

  我们在js部分,只需要通过jsonp请求道数据,然后按照模拟数据的格式,填充到ul里就行了。

  四、案例的js部分

  直接看代码

 1 <script src="js/jquery-3.3.1.js"></script>
 2 <script>
 3     function callback(data){
 4         //1.清空ul#wtInfo
 5         $("#wtInfo").html("");
 6         //2.呈现数据
 7         var wt = data.weather;
 8         $.each(wt,function(index,ele){
 9             var date = ele.date;
10             var day = ele.info.day;
11             var night = ele.info.night;
12             var tag = "<li>";
13             tag += "<h2>" + date + "</h2>";
14             tag += "<div class=‘day‘>";
15             tag += "<h3>白天天气</h3>";
16             tag += "<p>天气:" + day[1] + "</p>";
17             tag += "<p>温度:" + day[2] + "</p>";
18             tag += "<p>风向:" + day[3] + "</p>";
19             tag += "<p>风速:" + day[4] + "</p>";
20             tag += "</div>";
21             tag += "<div class=‘night‘>";
22             tag += "<h3>夜间天气</h3>";
23             tag += "<p>天气:" + night[1] + "</p>";
24             tag += "<p>温度:" + night[2] + "</p>";
25             tag += "<p>风向:" + night[3] + "</p>";
26             tag += "<p>风速:" + night[4] + "</p>";
27             tag += "</div>";
28             tag += "</li>";
29             $("#wtInfo").append(tag);
30         });
31     }
32     $(function () {
33         $("#btn").on("click",function () {
34             var cityCode = $("#selCity option:selected").val();
35             var url =
36                 ‘https://cdn.weather.hao.360.cn/sed_api_weather_info.PHP?app=hao360&_jsonp=callback&code=‘ +
37                 cityCode;
38             $("body").append($("<script src=‘" + url + "‘><script>"));
39         })
40     })
41 </script>

  代码解释:

  1.这用到了jQuery,所以第1行代码先引入了jQuery包

  2.jsonp的原理是通过<script>标签发出请求,而本例中不希望一打开网页就显示某一个城市的天气数据,而是要先选择一个,然后点击查询按钮,才发出请求,得到气象数据, 展示数据。

  3.所以我们的思路是:肯定不能在页面上写死那个做jsonp请求的<script src = "......">标签。我们的做法是,当点击按钮时,我们动态的获取到所选select标签中城市的code,然后拼写出待请求的url,最后在文档(document)的body标签底部,动态添加这个做jsonp请求的<script src = "......">标签。

  4.代码中定义的function callback(data)函数,就是用来做回调函数的,在这个回调函数中,主要功能就是解析json数据,然后填充到ul中。本身代码逻辑不复杂,就是拼写每个li,以及li里边的各项元素有点费事而已。

  五、后记

  这个案例,到这里就结束了。我再补充2点:

  1.这个案例中需要大量拼写HTML标签代码,这么做是相当费时费力的,而且容易出错;一旦开发一个复杂点的页面,这么做是非常痛苦的。如何改进?我们可以使用模板技术。前端模板插件很多,最流行的前端模板就是art-template.js,大家可以从网上下载。我在这里给出使用该模板改造本例后的js代码,具体这个art-template怎么用,大家看看他官服的demo就一目了然,非常简单。  

<script src="js/template.js"></script>
<script id="weatherTemp" type="text/html">
    <li>
        <h2><%= date %></h2>
        <div>
            <h3>白天天气</h3>
            <% for(var i=1; i < info.day.length; i++){%>
                <p><%= info.day[i]%></p>
            <% }%>
        </div>
        <div>
            <h3>夜间天气</h3>
            <% for(var i=1; i < info.night.length; i++){%>
                <p><%= info.night[i]%></p>
            <% }%>
        </div>
    </li>
</script>
<script>
    function callback(data) {
        //1.清空ul#wtInfo
        $("#wtInfo").html("");
        //2.呈现数据
        var wt = data.weather;
        $.each(wt,function (index,ele) {
            var html = template("weatherTemp",ele)
            $("#wtInfo").append(html);
        });
    }
    $(function () {
        $("#btn").on("click",function () {
            var cityCode = $("#selCity option:selected").val();
            var url =
                ‘https://cdn.weather.hao.360.cn/sed_api_weather_info.PHP?app=hao360&_jsonp=callback&code=‘ +
                cityCode;
            $("body").append($("<script src=‘" + url + "‘><script>"));
        })
    })
</script>

   2.如果我们每次都去分析别人的报文,那将是一个非常痛苦的过程。好在现在有专业的,专门提供数据服务的web api提供商,比如“聚合数据”,百度api商店等等,还有很多,大家可以去网上搜索下。其中有免费的,有付费的。比如聚合数据,申请账号是免费的,提供的服务有的免费,有的付费,不过即使是付费的,也可以免费使用1000次,对于我们学习来说1000次够玩了。

Android-天气预报Demo-JSON数据解析

Android-天气预报Demo-JSON数据解析

在上两篇博客,Android-解析JSON数据(JSON对象/JSON数组),Android-Gson解析JSON数据(JSON对象/JSON数组),是介绍了解析本地文件里面的JSON数据;

 

Android去访问外网的天气预报接口,解析天气预报返回的JSON数据;

天气API JSON返回方式

我测试一下请求北京的天气,链接为:https://www.sojson.com/open/api/weather/json.shtml?city=北京

返回成功状态为:200 ,失败为非200

天气API JSON返回方式(成功)

访问天气预报JSON数据:

https://www.sojson.com/open/api/weather/json.shtml?city=北京

 

天气预报返回的JSON数据:

{
    "tips":"注意:当前API已经停用,新API没有次数限制,详情查看===>https://www.sojson.com/blog/305.html。",
    "date":"20181224",
    "message":"Success !",
    "status":200,
    "city":"北京当前API已经停用,新API没有次数限制,详情查看:https://www.sojson.com/blog/305.html",
    "data":{
        "shidu":"50%",
        "pm25":81,
        "pm10":133,
        "quality":"轻度污染",
        "wendu":"-13",
        "ganmao":"儿童、老年人及心脏、呼吸系统疾病患者人群应减少长时间或高强度户外锻炼",
        "yesterday":{
            "date":"23日星期日",
            "sunrise":"07:33",
            "high":"高温 0.0℃",
            "low":"低温 -9.0℃",
            "sunset":"16:53",
            "aqi":47,
            "fx":"北风",
            "fl":"3-4级",
            "type":"晴",
            "notice":"愿你拥有比阳光明媚的心情"
        },
        "forecast":[
            {
                "date":"24日星期一",
                "sunrise":"07:33",
                "high":"高温 2.0℃",
                "low":"低温 -8.0℃",
                "sunset":"16:54",
                "aqi":62,
                "fx":"西南风",
                "fl":"<3级",
                "type":"晴",
                "notice":"愿你拥有比阳光明媚的心情"
            },
            {
                "date":"25日星期二",
                "sunrise":"07:34",
                "high":"高温 3.0℃",
                "low":"低温 -8.0℃",
                "sunset":"16:54",
                "aqi":90,
                "fx":"北风",
                "fl":"3-4级",
                "type":"晴",
                "notice":"愿你拥有比阳光明媚的心情"
            },
            {
                "date":"26日星期三",
                "sunrise":"07:34",
                "high":"高温 -2.0℃",
                "low":"低温 -9.0℃",
                "sunset":"16:55",
                "aqi":27,
                "fx":"东北风",
                "fl":"<3级",
                "type":"晴",
                "notice":"愿你拥有比阳光明媚的心情"
            },
            {
                "date":"27日星期四",
                "sunrise":"07:34",
                "high":"高温 -3.0℃",
                "low":"低温 -11.0℃",
                "sunset":"16:55",
                "aqi":27,
                "fx":"北风",
                "fl":"3-4级",
                "type":"多云",
                "notice":"阴晴之间,谨防紫外线侵扰"
            },
            {
                "date":"28日星期五",
                "sunrise":"07:35",
                "high":"高温 -3.0℃",
                "low":"低温 -10.0℃",
                "sunset":"16:56",
                "aqi":31,
                "fx":"北风",
                "fl":"3-4级",
                "type":"晴",
                "notice":"愿你拥有比阳光明媚的心情"
            }
        ]
    },
    "count":2
}

 


 

加权限:

  <!-- 访问网络是危险的行为,所以需要加入权限 -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- 外置存储Sdcard 读取权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <!-- 外置存储Sdcard 写入权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  

 定义 Forecast 实体Bean:

package liudeli.mynetwork01.entity;

/**
 *          {
 *                 "date":"24日星期一",
 *                 "sunrise":"07:33",
 *                 "high":"高温 2.0℃",
 *                 "low":"低温 -8.0℃",
 *                 "sunset":"16:54",
 *                 "aqi":62,
 *                 "fx":"西南风",
 *                 "fl":"<3级",
 *                 "type":"晴",
 *                 "notice":"愿你拥有比阳光明媚的心情"
 *             }
 */
public class Forecast {

    private String date;
    private String sunrise;
    private String high;

    private String low;
    private String sunset;
    private int api;

    private String fx;
    private String fl;
    private String type;
    private String notice;

    public Forecast() {
    }

    public Forecast(String date, String sunrise, String high, String low, String sunset, int api, String fx, String fl, String type, String notice) {
        this.date = date;
        this.sunrise = sunrise;
        this.high = high;
        this.low = low;
        this.sunset = sunset;
        this.api = api;
        this.fx = fx;
        this.fl = fl;
        this.type = type;
        this.notice = notice;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getSunrise() {
        return sunrise;
    }

    public void setSunrise(String sunrise) {
        this.sunrise = sunrise;
    }

    public String getHigh() {
        return high;
    }

    public void setHigh(String high) {
        this.high = high;
    }

    public String getLow() {
        return low;
    }

    public void setLow(String low) {
        this.low = low;
    }

    public String getSunset() {
        return sunset;
    }

    public void setSunset(String sunset) {
        this.sunset = sunset;
    }

    public int getApi() {
        return api;
    }

    public void setApi(int api) {
        this.api = api;
    }

    public String getFx() {
        return fx;
    }

    public void setFx(String fx) {
        this.fx = fx;
    }

    public String getFl() {
        return fl;
    }

    public void setFl(String fl) {
        this.fl = fl;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNotice() {
        return notice;
    }

    public void setNotice(String notice) {
        this.notice = notice;
    }

    @Override
    public String toString() {
        return "Forecast{" +
                "date=''" + date + ''\'''' +
                ", sunrise=''" + sunrise + ''\'''' +
                ", high=''" + high + ''\'''' +
                ", low=''" + low + ''\'''' +
                ", sunset=''" + sunset + ''\'''' +
                ", api=" + api +
                ", fx=''" + fx + ''\'''' +
                ", fl=''" + fl + ''\'''' +
                ", type=''" + type + ''\'''' +
                ", notice=''" + notice + ''\'''' +
                ''}'';
    }
}

 

具体实现代码:

package liudeli.mynetwork01;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;

import liudeli.mynetwork01.entity.Forecast;

public class WeatherActivity extends Activity {

    private final String TAG = WeatherActivity.class.getSimpleName();

    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_weather);

        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("提示");
        progressDialog.setMessage("正在获取网络上的天气预报信息");
        progressDialog.show();

        downloadWeatherDataInfo();

        saveJSONToFile();
    }

    private void saveJSONToFile() {
        // 保存文件到Sdcard
        File file = new File(Environment.getExternalStorageDirectory(), "weather.txt");
        try {
            Writer writer = new FileWriter(file);
            writer.write("{\n" +
                    "    \"tips\":\"注意:当前API已经停用,新API没有次数限制,详情查看===>https://www.sojson.com/blog/305.html。\",\n" +
                    "    \"date\":\"20181224\",\n" +
                    "    \"message\":\"Success !\",\n" +
                    "    \"status\":200,\n" +
                    "    \"city\":\"北京当前API已经停用,新API没有次数限制,详情查看:https://www.sojson.com/blog/305.html\",\n" +
                    "    \"data\":{\n" +
                    "        \"shidu\":\"50%\",\n" +
                    "        \"pm25\":81,\n" +
                    "        \"pm10\":133,\n" +
                    "        \"quality\":\"轻度污染\",\n" +
                    "        \"wendu\":\"-13\",\n" +
                    "        \"ganmao\":\"儿童、老年人及心脏、呼吸系统疾病患者人群应减少长时间或高强度户外锻炼\",\n" +
                    "        \"yesterday\":{\n" +
                    "            \"date\":\"23日星期日\",\n" +
                    "            \"sunrise\":\"07:33\",\n" +
                    "            \"high\":\"高温 0.0℃\",\n" +
                    "            \"low\":\"低温 -9.0℃\",\n" +
                    "            \"sunset\":\"16:53\",\n" +
                    "            \"aqi\":47,\n" +
                    "            \"fx\":\"北风\",\n" +
                    "            \"fl\":\"3-4级\",\n" +
                    "            \"type\":\"晴\",\n" +
                    "            \"notice\":\"愿你拥有比阳光明媚的心情\"\n" +
                    "        },\n" +
                    "        \"forecast\":[\n" +
                    "            {\n" +
                    "                \"date\":\"24日星期一\",\n" +
                    "                \"sunrise\":\"07:33\",\n" +
                    "                \"high\":\"高温 2.0℃\",\n" +
                    "                \"low\":\"低温 -8.0℃\",\n" +
                    "                \"sunset\":\"16:54\",\n" +
                    "                \"aqi\":62,\n" +
                    "                \"fx\":\"西南风\",\n" +
                    "                \"fl\":\"<3级\",\n" +
                    "                \"type\":\"晴\",\n" +
                    "                \"notice\":\"愿你拥有比阳光明媚的心情\"\n" +
                    "            },\n" +
                    "            {\n" +
                    "                \"date\":\"25日星期二\",\n" +
                    "                \"sunrise\":\"07:34\",\n" +
                    "                \"high\":\"高温 3.0℃\",\n" +
                    "                \"low\":\"低温 -8.0℃\",\n" +
                    "                \"sunset\":\"16:54\",\n" +
                    "                \"aqi\":90,\n" +
                    "                \"fx\":\"北风\",\n" +
                    "                \"fl\":\"3-4级\",\n" +
                    "                \"type\":\"晴\",\n" +
                    "                \"notice\":\"愿你拥有比阳光明媚的心情\"\n" +
                    "            },\n" +
                    "            {\n" +
                    "                \"date\":\"26日星期三\",\n" +
                    "                \"sunrise\":\"07:34\",\n" +
                    "                \"high\":\"高温 -2.0℃\",\n" +
                    "                \"low\":\"低温 -9.0℃\",\n" +
                    "                \"sunset\":\"16:55\",\n" +
                    "                \"aqi\":27,\n" +
                    "                \"fx\":\"东北风\",\n" +
                    "                \"fl\":\"<3级\",\n" +
                    "                \"type\":\"晴\",\n" +
                    "                \"notice\":\"愿你拥有比阳光明媚的心情\"\n" +
                    "            },\n" +
                    "            {\n" +
                    "                \"date\":\"27日星期四\",\n" +
                    "                \"sunrise\":\"07:34\",\n" +
                    "                \"high\":\"高温 -3.0℃\",\n" +
                    "                \"low\":\"低温 -11.0℃\",\n" +
                    "                \"sunset\":\"16:55\",\n" +
                    "                \"aqi\":27,\n" +
                    "                \"fx\":\"北风\",\n" +
                    "                \"fl\":\"3-4级\",\n" +
                    "                \"type\":\"多云\",\n" +
                    "                \"notice\":\"阴晴之间,谨防紫外线侵扰\"\n" +
                    "            },\n" +
                    "            {\n" +
                    "                \"date\":\"28日星期五\",\n" +
                    "                \"sunrise\":\"07:35\",\n" +
                    "                \"high\":\"高温 -3.0℃\",\n" +
                    "                \"low\":\"低温 -10.0℃\",\n" +
                    "                \"sunset\":\"16:56\",\n" +
                    "                \"aqi\":31,\n" +
                    "                \"fx\":\"北风\",\n" +
                    "                \"fl\":\"3-4级\",\n" +
                    "                \"type\":\"晴\",\n" +
                    "                \"notice\":\"愿你拥有比阳光明媚的心情\"\n" +
                    "            }\n" +
                    "        ]\n" +
                    "    },\n" +
                    "    \"count\":2\n" +
                    "}\n" +
                    "\n");
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 访问https://www.sojson.com/open/api/weather/json.shtml?city=北京
     * 获取北京天气预报数据信息
     */
    public void downloadWeatherDataInfo() {
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    // 把字符串地址包装成网络地址
                    URL url = new URL("https://www.sojson.com/open/api/weather/json.shtml?city=北京");
                    // 打开连接对象
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    // 设置连接超时时长
                    httpURLConnection.setConnectTimeout(5000);
                    // 设置请求方式Get
                    httpURLConnection.setRequestMethod("GET");

                    // 注意:是执行httpURLConnection.getResponseCode()的时候,才开始向服务器发送请求
                    int code = httpURLConnection.getResponseCode();
                    Log.d(TAG, ">>> run: code:" + code);

                    /**
                     * 现在由于访问受限,只能模拟去读文件里面的JSON数据,实际上和读取网络数据一模一样
                     */
                    code = 200;

                    if (code == HttpURLConnection.HTTP_OK) {
                        File file = new File(Environment.getExternalStorageDirectory(), "weather.txt");
                        if (!file.exists()) {
                            mHandler.sendEmptyMessageDelayed(REQUEST_ERROR, 1500); // delayMillis 是为了模仿网络弱
                            return;
                        }

                        InputStream fis = new FileInputStream(file);
                        byte[] bytes = new byte[fis.available()];
                        fis.read(bytes);

                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        baos.write(bytes, 0, bytes.length);

                        Message message = mHandler.obtainMessage();
                        message.what = REQUEST_SUCCESS;
                        message.obj = new String(baos.toByteArray());

                        mHandler.sendMessageDelayed(message, 1500); // delayMillis 是为了模仿网络弱
                    } else {
                        mHandler.sendEmptyMessageDelayed(REQUEST_ERROR, 1500); // delayMillis 是为了模仿网络弱
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    mHandler.sendEmptyMessage(REQUEST_ERROR);
                }
            }
        }.start();
    }

    private final int REQUEST_SUCCESS = 200;
    private final int REQUEST_ERROR = 400;
    private final int CLOSE = 1000;

    /**
     * Handler与子线程通讯
     */
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case REQUEST_ERROR:
                    progressDialog.setMessage("请求错误!");
                    mHandler.sendEmptyMessageDelayed(CLOSE, 1500); // delayMillis 是为了模仿网络弱
                    Log.d(TAG, "请求错误!");
                    break;
                case REQUEST_SUCCESS:
                    progressDialog.setMessage("恭喜,请求成功");
                    String successResult = (String) msg.obj;
                    handlerSuccessMethod(successResult);
                    mHandler.sendEmptyMessageDelayed(CLOSE, 1500); // delayMillis 是为了模仿网络弱
                    Log.d(TAG, "恭喜,请求成功");
                    break;
                case CLOSE:
                    progressDialog.dismiss();
                    Log.d(TAG, "CLOSE");
                    break;
            }
        }
    };

    /**
     * 请求成功后,拿到JSON数据
     * @param successResult JSON数据
     */
    private void handlerSuccessMethod(String successResult) {
        Log.d(TAG, "handlerSuccessMethod successResult:" + successResult);

        try{
            // 整体最大的JSON对象
            JSONObject jsonObjectALL = new JSONObject(successResult);
            Log.d(TAG, "解析后的数据:tips:" + jsonObjectALL.optString("tips", null));
            Log.d(TAG, "解析后的数据:date:" + jsonObjectALL.optString("date", null));
            Log.d(TAG, "解析后的数据:message:" + jsonObjectALL.optString("message", null));
            Log.d(TAG, "解析后的数据:status:" + jsonObjectALL.optString("status", null)); // 真实开发中要判断status==200
            Log.d(TAG, "解析后的数据:city:" + jsonObjectALL.optString("city", null));

            // data JSON 对象
            String data = jsonObjectALL.optString("data", null);
            JSONObject dataJSONObject = new JSONObject(data);
            Log.d(TAG, "解析后的数据:shidu:" + dataJSONObject.optString("shidu", null));
            Log.d(TAG, "解析后的数据:pm25:" + dataJSONObject.optString("pm25", null));
            Log.d(TAG, "解析后的数据:pm10:" + dataJSONObject.optString("pm10", null));
            Log.d(TAG, "解析后的数据:quality:" + dataJSONObject.optString("quality", null));
            Log.d(TAG, "解析后的数据:wendu:" + dataJSONObject.optString("wendu", null));
            Log.d(TAG, "解析后的数据:ganmao:" + dataJSONObject.optString("ganmao", null));

            // yesterday JSON 对象
            String yesterday = dataJSONObject.optString("yesterday");
            JSONObject yesterdayJSONObject = new JSONObject(yesterday);

            Log.d(TAG, "解析后的数据:date:" + yesterdayJSONObject.optString("date", null));
            Log.d(TAG, "解析后的数据:sunrise:" + yesterdayJSONObject.optString("sunrise", null));
            Log.d(TAG, "解析后的数据:high:" + yesterdayJSONObject.optString("high", null));
            Log.d(TAG, "解析后的数据:low:" + yesterdayJSONObject.optString("low", null));
            Log.d(TAG, "解析后的数据:sunset:" + yesterdayJSONObject.optString("sunset", null));
            Log.d(TAG, "解析后的数据:aqi:" + yesterdayJSONObject.optString("aqi", null));
            Log.d(TAG, "解析后的数据:fx:" + yesterdayJSONObject.optString("fx", null));
            Log.d(TAG, "解析后的数据:fl:" + yesterdayJSONObject.optString("fl", null));
            Log.d(TAG, "解析后的数据:type:" + yesterdayJSONObject.optString("type", null));
            Log.d(TAG, "解析后的数据:notice:" + yesterdayJSONObject.optString("notice", null));

            // forecast JSON [数组] 这种有规律的 JSON数组,我决定用 Gson 来得到集合
            // 注意:forecast 的标记key 是data
            String forecastJSONArray = dataJSONObject.optString("forecast", null);
            Gson gson = new Gson();
            List<Forecast> list = gson.fromJson(forecastJSONArray, new TypeToken<List<Forecast>>(){}.getType());
            for (Forecast f : list) {
                Log.d(TAG, "解析后的数据 f.toString:" + f.toString());
            }

            // 解析最后一个字段count,count的标记key是整个最大对象
            int count = jsonObjectALL.optInt("count", 0);
            Log.d(TAG, "解析后的数据 count:" + count);

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

 

解析后的结果:

 

12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:tips:注意:当前API已经停用,新API没有次数限制,详情查看===>https://www.sojson.com/blog/305.html。
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:date:20181224
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:message:Success !
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:status:200
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:city:北京当前API已经停用,新API没有次数限制,详情查看:https://www.sojson.com/blog/305.html
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:shidu:50%
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:pm25:81
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:pm10:133
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:quality:轻度污染
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:wendu:-13
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:ganmao:儿童、老年人及心脏、呼吸系统疾病患者人群应减少长时间或高强度户外锻炼
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:date:23日星期日
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:sunrise:07:33
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:high:高温 0.012-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:low:低温 -9.012-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:sunset:16:53
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:aqi:47
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:fx:北风
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:fl:3-4级
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:type:晴
12-24 08:02:59.486 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据:notice:愿你拥有比阳光明媚的心情
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 f.toString:Forecast{date=''24日星期一'', sunrise=''07:33'', high=''高温 2.0℃'', low=''低温 -8.0℃'', sunset=''16:54'', api=0, fx=''西南风'', fl=''<3级'', type=''晴'', notice=''愿你拥有比阳光明媚的心情''}
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 f.toString:Forecast{date=''25日星期二'', sunrise=''07:34'', high=''高温 3.0℃'', low=''低温 -8.0℃'', sunset=''16:54'', api=0, fx=''北风'', fl=''3-4级'', type=''晴'', notice=''愿你拥有比阳光明媚的心情''}
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 f.toString:Forecast{date=''26日星期三'', sunrise=''07:34'', high=''高温 -2.0℃'', low=''低温 -9.0℃'', sunset=''16:55'', api=0, fx=''东北风'', fl=''<3级'', type=''晴'', notice=''愿你拥有比阳光明媚的心情''}
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 f.toString:Forecast{date=''27日星期四'', sunrise=''07:34'', high=''高温 -3.0℃'', low=''低温 -11.0℃'', sunset=''16:55'', api=0, fx=''北风'', fl=''3-4级'', type=''多云'', notice=''阴晴之间,谨防紫外线侵扰''}
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 f.toString:Forecast{date=''28日星期五'', sunrise=''07:35'', high=''高温 -3.0℃'', low=''低温 -10.0℃'', sunset=''16:56'', api=0, fx=''北风'', fl=''3-4级'', type=''晴'', notice=''愿你拥有比阳光明媚的心情''}
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 解析后的数据 count:2
12-24 08:02:59.523 5179-5179/liudeli.mynetwork01 D/WeatherActivity: 恭喜,请求成功
12-24 08:03:01.076 5179-5179/liudeli.mynetwork01 D/WeatherActivity: CLOSE

 

今天关于jsonp技术访问天气Demo嘲笑鸡儿小的讲解已经结束,谢谢您的阅读,如果想了解更多关于@CosmosInput 无法识别 json 的 JsonProperty、ajax小demo---JSONP 跨域原理及简单应用、AJAX(七)jsonp实战--天气预报、Android-天气预报Demo-JSON数据解析的相关知识,请在本站搜索。

本文标签: