JSON(JavaScript Object Notation),一種基於JavaScrip表示法且用來傳輸由屬性值或者序列性的值組成的資料物件。
JSON由於它的特性,需多開源資料都支援JSON格式的表示。
JSON格式
JSON格式的詳細資料可以參考這個網站
以大括號包含資料,一個大括號為一個物件
裡面的資料成對表示,每組資料會有一個名稱和數值,類似Java中Map類別的概念
資料組和資料組之間以逗號分開
{name1: value1, name2: value2}
以中括號包含資料,一個中括號代表一個陣列
資料與資料間以逗號分隔
[value1, value2, value3]
而資料的形式可以為string, number, object, array, true, false, null
利用物件和陣列的搭配可以使JSON的資料表示更多樣化
YouBike JSON資料分析
以新北市公共自行車租賃系統(YouBike)的政府開源資料為例
得到JSON資料如以下所示
從這樣的資料外觀很難分析整體的資料架構,可以利用JSON beautify關鍵字找到很多線上工具將資料整理成易讀的格式
筆者使用 JSON Formatter & Validator,可將資料用以下的方式顯示
並且可用減號(-)把資料集收起來,對於JSON資料的分析會更清楚,更好設計相應的類別
觀察架構可以知道我們需要資料對應名稱為records
"records":[{name1, value1}, {name2, value2}, {name3, value3}]
records所對應的資料為一個陣列,陣列裡的元素為物件,每個物件裡包裹的就是我們所要的資料
而records資料組被包在result資料組中,利用這些關係可以用JSON相應API解析
Android實作
可參考筆者的另一篇文章,有更詳細的專案實作介紹
[Android] 使用RecyclerView顯示新北市YouBike站點資料
Android Studio內建有JSON API,若不是使用Android實作,像是用IntelliJ, NetBeans, Eclipse等
必須另外導入jar檔,可以到以下連結下載
由於網路資料相關處理較為耗時,使用覆寫AsyncTask類別中的方法doInBackground
在背景處理
連線到YoubBike站點資料,並且存取成String資料型態
@Override
protected String doInBackground(String... params) {
StringBuffer json = new StringBuffer();
try {
URL url = new URL(params[0]);
// params[0] = "http://data.ntpc.gov.tw/api/v1/rest/datastore/382000000A-000352-001"
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
while (line != null) {
json.append(line);
line = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
return json.toString();
}
覆寫AsyncTask類別中的方法onPostExecute
,處理在doInBackground
得到的String型態JSON資料
整包JSON資料為一個物件,這邊設定為jonObject
而result資料組的數值為一個物件,因此利用getJSONObject將result的物件從jonObject提取出來
JSONObject resultObj = jonObject.getJSONObject("result")
而records資料組的數值為陣列,使用getJSONArray將records的陣列從resultObj提取出來
JSONArray recordArray = resultObj.getJSONArray("records")
每個YouBike站點資訊被包裹成物件放在陣列recordArray
利用for迴圈將每個站點資訊提取出來放在設計的BIke物件裡
最後得到Bike集合,再將Bike集合利用RecyclerView的方式顯示出來
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
JSONObject jonObject = null;
List<Bike> bikes = new ArrayList<>();
try {
jonObject = new JSONObject(result.toString());
JSONObject resultObj = jonObject.getJSONObject("result");
JSONArray recordArray = resultObj.getJSONArray("records");
for (int i = 0; i < recordArray.length(); i++) {
JSONObject object = recordArray.getJSONObject(i);
String name = object.getString("sna");
String address = object.getString("ar");
String totalNumber = object.getString("tot");
String lendNumber = object.getString("sbi");
String returnNumber = object.getString("bemp");
String latitude = object.getString("lat");
String longitude = object.getString("lng");
bikes.add(new Bike(name, address, totalNumber,
lendNumber, returnNumber, latitude, longitude));
Log.d(TAG, "AsyncTask onPostExecute: " +
name + address+ totalNumber +
lendNumber + returnNumber +
latitude + longitude);
}
recycler.setAdapter(new BikeAdapter(bikes));
} catch (JSONException e) {
e.printStackTrace();
}
}