Android-Json數據解析之空氣質量檢測

一、JSON基礎

1.JSON優點:格式簡單,占寬帶小,多語言支持

2.JSON缺點:編碼必須是Unicode,語法過于嚴謹

但也因為JSON語法嚴謹(如四大基礎規則),才能支持多語言

3.JSON四大基礎規則:

(1)并列數據之間用逗號隔開(",");

(2)映射用冒號表示(":");

(3)并列數據集合集合(數組)用"[]"表示;

(4)映射的集合(對象)"{}"表示;


二、空氣質量檢測app開發

1.開發環境:

Android Studio 2.1.2(API:18~24)

空氣質量檢測API(https://www.juhe.cn/docs/api/id/33)

jdk1.8.0_91

2.工程開發:

(1)搭建工程

這里寫圖片描述

(2)空氣質量檢測API數據申請

申請api和key請上網站(https://www.juhe.cn/docs/api/id/33), 申請完之后數據將以JSON的格式返回,而讀者要做的就是請求數據和解析數據,就是這么簡單。
這里寫圖片描述
返回的數據我只是解析了其中的兩個,讀者可以根據自己需要解析更多的數據

(3)返回的JSON格式數據

{
    "resultcode": "200",
    "reason": "SUCCESSED!",
    "error_code": 0,
    "result": [
        {
            "citynow": {
                "city": "suzhou",
                "AQI": "77",
                "quality": "良",
                "date": "2014-05-09 14:00"
            },
            "lastTwoWeeks": {
                "1": {
                    "city": "suzhou",
                    "AQI": "100",
                    "quality": "良",
                    "date": "2014-05-08"
                },
                "2": {
                    "city": "suzhou",
                    "AQI": "99",
                    "quality": "良",
                    "date": "2014-05-07"
                },
                "3": {
                    "city": "suzhou",
                    "AQI": "77",
                    "quality": "良",
                    "date": "2014-05-06"
                },
                "4": {
                    "city": "suzhou",
                    "AQI": "75",
                    "quality": "良",
                    "date": "2014-05-05"
                },
                "5": {
                    "city": "suzhou",
                    "AQI": "78",
                    "quality": "良",
                    "date": "2014-05-04"
                },
                "6": {
                    "city": "suzhou",
                    "AQI": "84",
                    "quality": "良",
                    "date": "2014-05-03"
                },
                "7": {
                    "city": "suzhou",
                    "AQI": "135",
                    "quality": "輕度污染",
                    "date": "2014-05-02"
                },
                "8": {
                    "city": "suzhou",
                    "AQI": "126",
                    "quality": "輕度污染",
                    "date": "2014-05-01"
                },
                "9": {
                    "city": "suzhou",
                    "AQI": "87",
                    "quality": "良",
                    "date": "2014-04-30"
                },
                "10": {
                    "city": "suzhou",
                    "AQI": "97",
                    "quality": "良",
                    "date": "2014-04-29"
                },
                "11": {
                    "city": "suzhou",
                    "AQI": "77",
                    "quality": "良",
                    "date": "2014-04-28"
                },
                "12": {
                    "city": "suzhou",
                    "AQI": "84",
                    "quality": "良",
                    "date": "2014-04-27"
                },
                "13": {
                    "city": "suzhou",
                    "AQI": "45",
                    "quality": "優",
                    "date": "2014-04-26"
                },
                "14": {
                    "city": "suzhou",
                    "AQI": "56",
                    "quality": "良",
                    "date": "2014-04-25"
                },
                "15": {
                    "city": "suzhou",
                    "AQI": "83",
                    "quality": "良",
                    "date": "2014-04-24"
                },
                "16": {
                    "city": "suzhou",
                    "AQI": "95",
                    "quality": "良",
                    "date": "2014-04-23"
                },
                "17": {
                    "city": "suzhou",
                    "AQI": "101",
                    "quality": "輕度污染",
                    "date": "2014-04-22"
                }
            },
            "lastMoniData": {
                "1": {
                    "city": "上方山",
                    "AQI": "77",
                    "quality": "良",
                    "PM2.5Hour": "46μg/m3",
                    "PM2.5Day": "46μg/m3",
                    "PM10Hour": "104μg/m3",
                    "lat": "31.247222",
                    "lon": "120.561389"
                },
                "2": {
                    "city": "南門",
                    "AQI": "112",
                    "quality": "輕度污染",
                    "PM2.5Hour": "84μg/m3",
                    "PM2.5Day": "84μg/m3",
                    "PM10Hour": "—μg/m3",
                    "lat": "31.286389",
                    "lon": "120.6275"
                },
                "3": {
                    "city": "彩香",
                    "AQI": "76",
                    "quality": "良",
                    "PM2.5Hour": "46μg/m3",
                    "PM2.5Day": "46μg/m3",
                    "PM10Hour": "101μg/m3",
                    "lat": "31.301944",
                    "lon": "120.590833"
                },
                "4": {
                    "city": "軋鋼廠",
                    "AQI": "68",
                    "quality": "良",
                    "PM2.5Hour": "41μg/m3",
                    "PM2.5Day": "41μg/m3",
                    "PM10Hour": "85μg/m3",
                    "lat": "31.326389",
                    "lon": "120.595556"
                },
                "5": {
                    "city": "吳中區",
                    "AQI": "64",
                    "quality": "良",
                    "PM2.5Hour": "46μg/m3",
                    "PM2.5Day": "46μg/m3",
                    "PM10Hour": "—μg/m3",
                    "lat": "31.270278",
                    "lon": "120.612778"
                },
                "6": {
                    "city": "蘇州新區",
                    "AQI": "72",
                    "quality": "良",
                    "PM2.5Hour": "46μg/m3",
                    "PM2.5Day": "46μg/m3",
                    "PM10Hour": "93μg/m3",
                    "lat": "31.299444",
                    "lon": "120.543333"
                },
                "7": {
                    "city": "蘇州工業園區",
                    "AQI": "82",
                    "quality": "良",
                    "PM2.5Hour": "60μg/m3",
                    "PM2.5Day": "60μg/m3",
                    "PM10Hour": "88μg/m3",
                    "lat": "31.309722",
                    "lon": "120.669167"
                }
            }
        }
    ]
}

讀者謹記:在JSON中,"[ ]"指的是數組(集合),"{ }"指的是對象

(3)代碼編寫

activity_main.xml如下所示
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.whetherreporter.MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            android:text="@string/cityName"
            android:textSize="25sp" />

        <EditText
            android:id="@+id/cityName"
            android:layout_width="297dp"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <Button
        android:id="@+id/submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/submit"
        android:textSize="25sp" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/show"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textColor="#000"
            android:textSize="18sp" />
    </ScrollView>
</LinearLayout>

界面比較丑,讀者可以根據自己需要修改界面,其實認真寫好界面,不失為一款好的應用

strings.xml如下所示
<resources>
    <string name="cityName">城市:</string>
    <string name="submit">提交</string>
    <string name="app_name"></string>
    <string name="city">城市</string>
    <string name="AQI">空氣質量指數</string>
    <string name="quality">空氣質量</string>
    <string name="time">更新時間</string>
    <string name="loc">地點</string>
    <string name="PM2.5Hour">PM2.5Hour</string>
    <string name="PM2.5Day">PM2.5Day</string>
    <string name="PM10">PM10Hour</string>
    <string name="lat">維度</string>
    <string name="lon">經度</string>
</resources>
MainActivity.java 如下所示
package com.example.administrator.whetherreporter;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Created by Sean on 2016/8/11.
 */

public class MainActivity extends AppCompatActivity {
    private EditText et_cityName;
    private Button btn_submit;
    private TextView tv_show;
    private Task task;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_cityName= (EditText) findViewById(R.id.cityName);
        btn_submit= (Button) findViewById(R.id.submit);
        tv_show= (TextView) findViewById(R.id.show);
        btn_submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String cityName=et_cityName.getText().toString();
                if (cityName.length()<1){
                    Toast.makeText(MainActivity.this,
                            "請輸入城市的名字",Toast.LENGTH_SHORT).show();
                    return;
                }
                else {
                    //開啟多線程,一般將比較耗時的操作交給另一條線程
                    task=new Task(MainActivity.this,tv_show);  
                    task.execute(cityName);
                }
            }
        });
    }
}

Taks.java 如下所示
package com.example.administrator.whetherreporter;

import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;

/**
 * Created by Sean on 2016/8/11.
 */

public class Task extends AsyncTask<String, Void, String> {
    private TextView tv_show;
    private Context context;
    //獲取的API接口
    private static final String url = "http://web.juhe.cn:8080/environment/air/cityair";
    //獲取的API的key
    private static final String key = "8118a1d36116d6e89f543163055d7530";

    public Task(Context context, TextView tv_show) {
        this.context = context;
        this.tv_show = tv_show;
    }

    /***
     *
     * 通過API請求數據
     * @param strings :從主線程中執行子線程傳入的字符串,即cityName
     * @return        :請求API之后返回的JSON格式數據
     */
    @Override
    protected String doInBackground(String... strings) {
        String city = strings[0];
        ArrayList<NameValuePair> firstList = new ArrayList<NameValuePair>();
        //設置訪問文本類型
        firstList.add(new BasicNameValuePair("Content-Type", "text/html,charset=utf-8"));

        String targetUrl = url;
        //請求的參數
        ArrayList<NameValuePair> paramsList = new ArrayList<NameValuePair>();
        paramsList.add(new BasicNameValuePair("city", city));
        paramsList.add(new BasicNameValuePair("key", key));

        for (int i = 0; i < paramsList.size(); i++) {
            NameValuePair nowPair = paramsList.get(i);
            String value = nowPair.getValue();
            try {
                value = URLEncoder.encode(value, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            if (i == 0) {
                targetUrl += ("?" + nowPair.getName() + "=" + value);
            } else {
                targetUrl += ("&" + nowPair.getName() + "=" + value);
            }
        }
        //以Get的形式訪問
        HttpGet httpGet = new HttpGet(targetUrl);
        try {
            for (int i = 0; i < firstList.size(); i++) {
                    httpGet.addHeader(firstList.get(i).getName(),       firstList.get(i).getValue());
            }

            HttpClient httpClient = new DefaultHttpClient();

            HttpResponse httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode()==200){
                String result= EntityUtils.toString(httpResponse.getEntity());
                return result;
            }
            else
                return null;
        } catch (IOException e) {
            e.printStackTrace();
        }


        return null;
    }

    /***
     *
     * 解析返回的數據
     * @param s   :請求之后返回的數據
     */
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s!=null){
            try {
                JSONObject jsonObject=new JSONObject(s);
                int resultCode=jsonObject.getInt("resultcode");
                if (resultCode==200){
                    JSONArray resultArray=jsonObject.getJSONArray("result");
                    JSONObject resultJsonObject = resultArray.getJSONObject(0);
                    JSONObject A= (JSONObject) resultJsonObject.get("citynow");
                    JSONObject B= (JSONObject) resultJsonObject.get("lastMoniData");

                    String division="---------------------------------------------";
                    
                    String output=
                             context.getString(R.string.city)+":"+A.optString("city")+"\n"
                            +context.getString(R.string.AQI)+":"+A.optString("AQI")+"\n"
                            +context.getString(R.string.quality)+":"+A.optString("quality")+"\n"
                            +context.getString(R.string.time)+":"+A.optString("date")+"\n"
                            +division+"\n"
                            +"監測點數據"+"\n";
                    for (int i=0;i<B.length();i++) {
                        int w=i+1;
                        String n=Integer.toString(w);
                        JSONObject C= (JSONObject) B.get(n);
                        output=output
                                + context.getString(R.string.loc) + ":" + C.optString("city") + "\n"
                                + context.getString(R.string.AQI) + ":" + C.optString("AQI") + "\n"
                                + context.getString(R.string.quality) + ":" + C.optString("quality") + "\n"
                                + context.getString(R.string.PM10) + ":" + C.optString("PM10Hour") + "\n"
                                + context.getString(R.string.PM2_5Hour) + ":" + C.optString("PM2.5Hour") + "\n"
                                + context.getString(R.string.PM2_5Day) + ":" + C.optString("PM2.5Day") + "\n"
                                + context.getString(R.string.lat) + ":" + C.optString("lat") + "\n"
                                + context.getString(R.string.lon) + ":" + C.optString("lon") + "\n";
                    }
                    tv_show.setText(output);
                }
                else if (resultCode==202){
                    String reason=jsonObject.getString("reason");
                    tv_show.setText(reason);
                }
                else{
                    Toast.makeText(context, "查詢失敗",
                            Toast.LENGTH_LONG).show();
                    tv_show.setText("");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
        else {
            Toast.makeText(context, "查詢失敗",
                    Toast.LENGTH_LONG).show();
            tv_show.setText("");
        }
    }
}

*注意:類NameValuePair在Android API22的是后就已經過時了,可以用到類ContentValue來代替,使用方式如下圖所示 *


這里寫圖片描述

HttpGet 和 HttpClient 需要讀者自己導入第三方包

這里寫圖片描述

三、測試

這里寫圖片描述

這里寫圖片描述

由于API本身的局限性,所以有些地方數據可能有問題,請包涵!


That's all , 感謝您的閱讀,之后我會將我的項目發布到GitHub。

請大家尊重原創者版權,轉載請標明出處 http://blog.csdn.net/AAAAA_Sean_M/article/details/52183277

參考:http://blog.csdn.net/hantangsongming/article/details/42234293

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,613評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,151評論 4 61
  • 朋友,請不要憂傷 (一) 拭去你面頰的淚光。 收回你雜亂的心網, 想一想愉快的往事。 丟掉不該有的愁悵, 無論實業...
    何立紅閱讀 313評論 0 0
  • 相識是一種緣,相知是一種情。 遇到最好的她,遇見最癡的你。 雖然沒有錢,雖然不懂浪漫,但是卻懂得溫情。 雖然一路很...
    風中沙粒閱讀 171評論 0 0