2017年1月7日土曜日

JSONを確認出来るweb toolでRESTのデータを見てみる(2)

ちょっと複雑な例を見てみます
以前は、heartrails expressというサイトで時刻表データが取得できたのですが、見当たらなくなってしまったので、一つ前の投稿の参考urlで紹介されていた"つつじバス"を見てみます
(heartrails expressのAPIは2015.09頃"公開停止中"というtwitterのログがありました)

http://www.city.sabae.fukui.jp/users/tutujibus/web-api/web-api.html

リクエストURLで簡単そうな例を探すと、02の"路線毎の時刻表データ"が良さそうです
http://www.city.sabae.fukui.jp/users/tutujibus/web-api/02.html

リクエストURLを下記のようにしてデータを取得してみます
http://tutujibus.com/timetableLookup.php/?rosenid=2

結果を整形してみます...の前に、ざっくり構造を調べてみます
timetalbe : 以下の配列
 bindid : 便番号  << この便番号毎に配列になっていて、中に時刻表配列が入っている
 *** 中略 (ドキュメント参照)
 list : 時刻表配列
    {
      time : 時刻
     busstopid : バス停番号
    }
 
 binid : 次の便番号
 *** 中略 (ドキュメント参照)
  list : 時刻表配列
  *** 以下同様に続く

となっているようです

{
    "timetable": [
        {
            "binid": "1",
            "konendaigakucd": "3",
            "weekdaycd": "3",
            "wintercd": "3",
            "destination": "嚮陽会館",
            "list": [
                {
                    "time": "08:55:00",
                    "busstopid": "45"
                },
          // *** 中略 ***
                {
                    "time": "09:21:00",
                    "busstopid": "61"
                }
            ]
        },
        {
            "binid": "2",
            "konendaigakucd": "3",
            "weekdaycd": "3",
            "wintercd": "3",
            "destination": "嚮陽会館",
            "list": [
                {
                    "time": "12:00:00",
                    "busstopid": "45"
                },
                // *** 中略 ***
                {
                    "time": "12:26:00",
                    "busstopid": "61"
                }
            ]
        },
        {
            "binid": "3",
            "konendaigakucd": "3",
            "weekdaycd": "3",
            "wintercd": "3",
            "destination": "嚮陽会館",
            "list": [
                {
                    "time": "15:50:00",
                    "busstopid": "45"
                },
          // *** 中略 ***
                {
                    "time": "16:16:00",
                    "busstopid": "61"
                }
            ]
        }
    ]
}

JSONを確認出来るweb toolでRESTのデータを見てみる

RESTで取得したjsonデータをペーストすると、整形してくれるサイトです。
java script(ローカル)で動いているそうなので、心配しなくても良さそう?です。

https://syncer.jp/json-prettyprint

API
wether hacks
http://weather.livedoor.com/weather_hacks/

こちらを整形してもらうと、以下の出力が得られました。
構造としては、
pinpointLocations : valueの配列
  link : url
  name : 都市名
    の配列が続く
link : リクエストしたurl(長野市と思われる2020100になっている)
forecasts : 日付ごとの配列 (今日・明日の2つ)
 dataLabel : 日付
 telop : 概略
 date : 日付
 temperature : maxとminのobject
 image : 図など
location : 場所の説明
  中略
title : タイトル
desctiption : 天気概要



{
    "pinpointLocations": [
        {
            "link": "http://weather.livedoor.com/area/forecast/2020100",
            "name": "長野市"
        },
        {
            "link": "http://weather.livedoor.com/area/forecast/2020111",
            "name": "長野"
        },
        {
            "link": "http://weather.livedoor.com/area/forecast/2020112",
            "name": "鬼無里戸隠"
        },
        // *** 中略 ***
        {
            "link": "http://weather.livedoor.com/area/forecast/2060200",
            "name": "栄村"
        }
    ],
    "link": "http://weather.livedoor.com/area/forecast/200010",
    "forecasts": [
        {
            "dateLabel": "今日",
            "telop": "曇のち雪",
            "date": "2017-01-09",
            "temperature": {
                "min": null,
                "max": {
                    "celsius": "6",
                    "fahrenheit": "42.8"
                }
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/14.gif",
                "title": "曇のち雪",
                "height": 31
            }
        },
        {
            "dateLabel": "明日",
            "telop": "曇時々雪",
            "date": "2017-01-10",
            "temperature": {
                "min": {
                    "celsius": "0",
                    "fahrenheit": "32.0"
                },
                "max": {
                    "celsius": "6",
                    "fahrenheit": "42.8"
                }
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/11.gif",
                "title": "曇時々雪",
                "height": 31
            }
        },
        {
            "dateLabel": "明後日",
            "telop": "曇時々雪",
            "date": "2017-01-11",
            "temperature": {
                "min": null,
                "max": null
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/11.gif",
                "title": "曇時々雪",
                "height": 31
            }
        }
    ],
    "location": {
        "city": "長野",
        "area": "信越・北陸",
        "prefecture": "長野県"
    },
    "publicTime": "2017-01-09T11:00:00+0900",
    "copyright": {
        "provider": [
            {
                "link": "http://tenki.jp/",
                "name": "日本気象協会"
            }
        ],
        "link": "http://weather.livedoor.com/",
        "title": "(C) LINE Corporation",
        "image": {
            "width": 118,
            "link": "http://weather.livedoor.com/",
            "url": "http://weather.livedoor.com/img/cmn/livedoor.gif",
            "title": "livedoor 天気情報",
            "height": 26
        }
    },
    "title": "長野県 長野 の天気",
    "description": {
        "text": " 低気圧が関東の東海上を発達しながら東北東へ進んでいます。\n\n 長野県内は、曇りまたは晴れとなっています。\n\n 9日は、冬型の気圧配置となりますが、寒気の影響を受ける見込みです。\n このため、北部では、曇りで夜は雪となり、雷を伴う所があるでしょう。\n中部と南部では、晴れで夕方からは曇りとなり、中部では夜は雪の降る所が\nあるでしょう。\n\n 10日は、冬型の気圧配置が続きますが、寒気の影響を受ける見込みです\n。\n このため、北部では、曇りで朝晩は雪となり、夜は雷を伴う所があるでし\nょう。中部と南部では、晴れますが、夜は雲が広がり、乗鞍上高地地域では\n雪が降るでしょう。",
        "publicTime": "2017-01-09T11:23:00+0900"
    }
}

Web APIのサイト紹介
https://wp-d.org/2013/03/14/3348/

2017年1月6日金曜日

XCode + Swift2の画面遷移とコード

Viewについては、"Main.storyboard"をGUI操作で画面を作っていくようです。
単一画面の場合は
1. Main.storyboardをクリック
  View Controller Sceneが配置されている
2. View ControllerにUIパーツを貼っていく
3. IBAction / IBOutletでViewController.swiftとView controllerを紐付けする
4. ViewController.swiftにコードを書いていく
と言った手順で
- ViewController (View)
- *.swift (ソースコード)
を紐付けて作っていくようです。

画面が二つ以上の場合は、"Navigation Controller"を使う事で画面を切り替えていくようです。

1. Main.storyboard をクリック
  View Controller Sceneが配置されている  << ここまでは同じ
2. View Controller Sceneを選択
3. メニューの"Editor -> Embed In -> Navigation controller"を選択
  > (Document outline = 左から2ペイン目に)Navigation Controller Sceneが追加される
  > GUIでMain.Storyboardの"-> Navigation controller -> View Controller"に接続されている事を確認
※ Navigation controlleにより、View controller(defaultの画面)と2画面目を階層的にコントロールできる為に上記そうさをするとの事

4. 1画面目(View controller)の画面を作っていく
  > "Bar Button Item"をドラッグするとNavigation Barの中にNavigation Itemが追加される(画面遷移に関連)

2画面目を作る
5. (際左ペインで)MainStory boardを選択
6. Object library(toolboxみたいなの)でview controllerを探して、story board(GUI画面)にドラッグドロップ
  > 画面が追加される...但し、矢印は接続されていない
   > Document outline (= 左から2ペイン目)にも"View controller Scene"が新たに追加される
Segueを追加する
7. 1画面目(最初からあった画面)から遷移する場合、1画面目をクリック
  > 画面上の"View controller"の□が選択される
  ※ うまく行かなかったので、menu barのボタンからドラッグした
8. command key を押しながら追加した画面(2画面目)にドラッグドロップする
9. 黒い(segue用の)ポップアップが出るので"Show"を選択する
 > これにより、1画面目から2画面目に矢印が接続される
 > 2画面目上部にもNavigation Barが追加されている
10. Segue object(矢印部分)を選択して-^-(Atribute Inspector)の"Identifier"でSegueの名前を変えられるので、必要に応じて変更する
※ この状態では実行させても、(4で追加したコントロールをクリックして)画面遷移させようとしても出来ない。下記操作をする事

ViewControllerの追加(2画面めに対応した*.swiftの事)
11. Project Navigator(再左ペイン)でFile-> New -> New File をクリック
  > "choose a template for your new file"ダイアログが表示される
12. iOS -> Source -> Cocoa Touch Classを選択してnext (上記ダイアログ)
13. クラス名を記載(***ViewControllerとか)
14. sub classをUI View Controllerにする
15. (言語はSwiftのままで)Next、そしてCreateボタん
  > ***ViewController.swiftが生成される

ViewController(2画面めのGUI)と紐付けする
16. Main.storyboard -> 2画面目のViewController Scene -> ViewControllerを選択
17. (際右ペインを)Identifer Inspector(-^-の隣の□アイコン)とする
18. Custom classの項目のclassに****ViewControllerを記載する (***ViewController.swiftのクラス名)
  > Document outline (= 左から2ペイン目)で"View controller scene"となっていた部分が*** View Controller Seceneに変わる
これで関連付け完了

やり方その1
2画面目から戻る (遷移時と同様、GUIで設定)
19. 決定ボタンなどを追加したら、同様にCtrl + ドラッグで1画面目にドラッグする
20. 同様にIDを設定

やり方その2
2画面目から戻る (コードで記述)
    // コードで戻る (返り値対応で、_をつけるらしい) / ボタン押下で戻る
    @IBAction func returnButtonAction(sender: AnyObject) {
        _ = navigationController?.popViewControllerAnimated(true)
    }


とりあえず、これで行ったり来たりは出来るようになった...

参考
https://iphone-app-tec.com/ios/tap_gesture.html

2017年1月5日木曜日

jsonのdataを取得して解析する

urlからdataを取得する辺りから書くと下記のような感じ

class ViewController: UIViewController,NSXMLParserDelegate {

    @IBOutlet weak var jsonTextView: UITextView!
    
    @IBAction func Button_GetJson(sender: AnyObject) {
        // let url:NSURL = NSURL(string: "http://editors.ascii.jp/c-minamoto/swift/swift-5-data.xml")!
        // let request = NSURLRequest(URL: url)
        
        //make URL of google feed api
        let urlString = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml&num=8"
        let url = NSURL(string: urlString)
        // var titles:String = ""
        
        //download by NSSession
        let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler:{data, response, error in
            //convert json data to dictionary
            var dict:NSDictionary
            do {
                dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
                //get responseData, feed, entries
                let responseData = dict["responseData"] as! NSDictionary
                let feed = responseData["feed"] as! NSDictionary
                let entries = feed["entries"] as! NSArray
                
                //extract entries
                // print(entries.count)
                var titles:String = ""
                for entry in entries {
                    // print(entry["title"])
                    let title:String = entry["title"] as! String
                    titles += title + ":"
                }
                // print(titles)
                dispatch_async(dispatch_get_main_queue()){
                    self.jsonTextView.text = titles
                }
            } catch {
                print("error")
                return
            }
            // print(dict)
        })
        task.resume()
        // self.jsonTextView.text = titles
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }






2017年1月3日火曜日

jsonのdataをswift2で解析する

取得するデータの構造は
responseData:
  feed:
    value
       feeUrl : "value"
       ...  // *** 以下"キー:value"のメンバが続く
       entries:  // *** ここがおめあて
          value配列
             ...

とした場合、以下コードで最終亭なentriesキーのvalue配列が取得できました。
var dict:NSDictionary
dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
//get responseData, feed, entries
let responseData = dict["responseData"] as! NSDictionary  // dictからresponseDataキーを探す
let feed = responseData["feed"] as! NSDictionary       // responseData からfeedキーを探す
let entries = feed["entries"] as! NSArray           // feedからentriesを探す..."entries"が配列として格納

entriesの配列の各titleを表示させる場合は以下になります。
//extract entries
// print(entries.count)
var titles:String = ""
for entry in entries {
 // print(entry["title"])
 let title:String = entry["title"] as! String
   titles += title + ":"
 }
 // print(titles)
 dispatch_async(dispatch_get_main_queue()){
  self.jsonTextView.text = titles
 }

2017年1月2日月曜日

Jsonで取得したデータは??

いろいろなページを参考にさせていただき、swiftでjsonを取得できました。
順序が逆になりますが、「実際はどんな風になっているか」を先に見てみます。

おそらく、"[]"については見えていないので、解る部分を見てみます。
取得したデータを字下げすると..(あと、注釈を追記)

{"responseData":     // *** ここのキーに対して、以下がvalueになる
  {"feed":       //  *** ここのキーに対して、以下がvalueになる
    { "feedUrl":"http://rss.itmedia.co.jp/rss/2.0/news_bursts.xml",  // *** キーとvalueのペアが続く
     "title":"ITmedia News 速報 最新記事一覧",
     "link":"http://www.itmedia.co.jp/news/bursts/",
     "author":"",
     "description":"ITmedia News 速報 の最新記事一覧です。",
     "type":"rss20",
     "entries":[  // *** ここから"entries"キーに対するvalueの配列が続く
       {            // *** "num=8"で要求したから? "entries"は8要素
           "title":"Raspberry Piの「PIXEL」が旧型PCやMacで稼働可能に",
           "link":"http://rss.rssad.jp/rss/artclk/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112?ul\u003dsWKI1zepQzDjpc7XC5rf2ewet1rxJmiV3BfQpFpgnr_Gr3.DNzTmu3CCs_zsy5TrxdEQvaf_o0e.p0eWYi3NUsxMHLApbJ70ELi0D_9ACLaN8lSZTT7.lFJN5cfjipmt5hi0Set",
           "author":"",
           "publishedDate":"Thu, 22 Dec 2016 14:18:00 -0800",
           "contentSnippet":"小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n",
           "content":"\u003cp\u003e小型コンピュータ「Raspberry Pi」のデスクトップ環境「PIXEL」のx86版が公開された。まだ実験的な段階だが、USBメモリに入れて起動ディスクとし、古いPCやMacでブートできる。\n\u003cimg border\u003d\"0\" width\u003d\"1\" height\u003d\"1\" src\u003d\"http://rss.rssad.jp/rss/artimg/XXtgw_wVjwMW/aa457f16b6ee2da4867bda91a84c3112\"\u003e\u003c/p\u003e",
          "categories":[]
       },    // *** ここまでが"entries"キーに対するvalueの配列の一つ目、そして次のvalueが続く
...
まとめると、以下のような感じと思ってます
responseData:
  feed:
    value
       feeUrl : "value"
       ...  // *** 以下"キー:value"のメンバが続く
       entries:  // *** ここがおめあて
          value配列
             ...

具体的にswiftで取得する方法は次回

2017年1月1日日曜日

jsonって??

最近はXMLからJSONに移行しつつあるそうです。
(SOAP->REST, XML->JSONなんですかね)

urlからデータを取得すると複雑な感じですが、基本は下記のような感じだそうです。

[
 {
   "番号":0,"タイトル":"とある本","ISBN":12345678
 },
 {
  "番号":1,"タイトル":"次に読む本","ISBN":2345678, "ユーザ":["mr a", "mr b", "miss a"]
 },
  ...
]

読み方は以下が基本のようです
{...} オブジェクトの表記(カッコ内がオブジェクト)
key:value ペアをコロンで記述する。ペアが複数ある場合はカンマで区切る << "メンバー"というようです
["value a", "value b", value c"] valueを配列で表すことができる

こちらのページが参考になりました
http://dev.classmethod.jp/etc/concrete-example-of-json/