-->

2017年02月

JSON(文字列) => オブジェクトに変換する。

[ { "name":"山田太郎", "age":22 }, { "name\":"山田花子", "age":24 } ]

こんなやつを扱う。

次のusingをソースに追加しておく。

using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using System.Diagnostics;

データのクラスを用意する。

    [DataContract]
    public class Person
    {
        [DataMember(Name="name")]
        public string Name { get; set; }
        [DataMember(Name="age")]
        public int Age { get; set; }
    }

変換する処理はこんな感じだ。

            // JSON(文字列)を用意
            var jsonStr = "[ { \"name\":\"山田太郎\", \"age\":22 }, { \"name\":\"山田花子\", \"age\":24 } ]";

            // 文字列をバイト配列にしてメモリーストリームに追加する。
            using (var memStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonStr)))
            {
                // シリアライザーを用意
                var serializer = new DataContractJsonSerializer(typeof(List<Person>));
                // メモリストリームから読み込んでオブジェクトに変換する。
                var jsonObject = serializer.ReadObject(memStream) as List<Person>;
                // 内容を表示
                jsonObject.ForEach(person => Debug.WriteLine("{0},{1}", person.Name, person.Age));
            }

実行すると、次のように出力される。

山田太郎,22
山田花子,24

JSONオブジェクト => JSON(文字列)に変換する。

            // JSONオブジェクトを用意
            var jsonObject = new List<Person>()
            {
                new Person() { Name="山田太郎", Age=22 },
                new Person() { Name="山田花子", Age=24 }
            };
            // メモリストリームを用意
            using (var memStream = new MemoryStream())
            {
                // シリアライザーを用意
                var serializer = new DataContractJsonSerializer(typeof(List<Person>));
                // JSONオブジェクトを変換してメモリーストリームに書き込む
                serializer.WriteObject(memStream, jsonObject);
                // メモリーストリームの内容を文字列に変換する。
                var jsonStr = System.Text.Encoding.UTF8.GetString(memStream.ToArray());
                // 表示する
                Debug.WriteLine(jsonStr);
            }

実行すると、次のように出力される。

[{"age":22,"name":"山田太郎"},{"age":24,"name":"山田花子"}]



このエントリーをはてなブックマークに追加

SQLite Download PageからUniversal Windows Platformのvsixファイルをダウンロードしてインストールする。

プロジェクトを開いて、参照マネージャーで
SQLite for Universal Windows Platform
Visual C++ 2015 for Universal Windows Platform Apps
を選択する。

001

NuGetパッケージマネージャーを起動して、SQLite.Net-PCLを検索してインストールする。

002

[Java] SQLiteを使う。と同じことをやってみる。
ソースの頭の方に

using SQLite.Net;
using SQLite.Net.Attributes;
using SQLite.Net.Platform.WinRT;

を追加する。

作るテーブルのクラスを用意する。

    public class test
    {
        [PrimaryKey]
        public int id { get; set; }
        public string name { get; set; }
    }

テーブル作ったり、データ追加したり、検索したりするのはこんな感じになる。

            var dbFilename = Path.Combine(ApplicationData.Current.TemporaryFolder.Path, "test.db");
            Debug.WriteLine(dbFilename);

            // データベースをオープン
            using (var conn = new SQLiteConnection(new SQLitePlatformWinRT(), dbFilename))
            {
                // テーブルを作成
                conn.CreateTable<test>();

                // データを登録
                for(int i = 0; i < 10; i++)
                {
                    conn.Insert(new test()
                    {
                        id = i,
                        name = "hoge" + i
                    });
                }

                // データを検索
                var sql = "SELECT * FROM test";
                var list = conn.Query<test>(sql);
                foreach(var d in list)
                {
                    Debug.WriteLine("{0},{1}", d.id, d.name);
                }
            }

(追記)
テーブルのクラス名と実際のテーブル名が違う場合は、アトリビュートTableで実際のテーブル名を指定する。プロパティ名とテーブルのカラム名が違う場合はColumnを指定する。
こんな感じだ。

    [Table("test")]
    public class Test
    {
        [PrimaryKey, Column("id")]
        public int Id { get; set; }
        [Column("name")]
        public string Name { get; set; }
    }


このエントリーをはてなブックマークに追加

さて、どうやって使うんだろーとグーグル先生に尋ねてみると
GRDBでSQLiteデータベースを使う(Swift3.0) - Swiftサラリーマンにたどり着いた。このサイトではCocoaPodsを使っているみたいなんだが、ここでは手動でやってみようと思う。macOSを対象にやっていくが、iOSでも同じような感じだ。

ここからダウンロードして展開しておく。
Sqliteを使うプロジェクトを用意して、ダウンロードしたGRDBにあるGRDB.xcodeprojを追加する。メニューのFile - Add Files to "〜〜"で追加する。

001

Target DependenciesのBuild PhasesにmacOSならGRDBOSX、iOSならGRDBiOSを追加する。
Target DependenciesのBuild Phasesはプロジェクトを選んでBuild Phasesタブを選択するとそこにある。

002

+ ボタンを押してGRDBOSX(GRDBiOS)を追加する。

003

GeneralのEmbedded BinariesにGRDB.frameworkを追加する。
GeneralのEmbedded Binariesはプロジェクトを選んでGeneralタブを選択するとそこにある。

004

+ ボタンを押してGRDB.frameworkを追加する。

005

[Java] SQLiteを使う。と同じことをやってみる。
ソースの頭の方に

import GRDB

を追加する。
テーブル作ったり、データ追加したり、検索したりするのはこんな感じになる。

        let dbFilename = NSTemporaryDirectory() + "test.db"
        print(dbFilename)
        do {
            let dbQueue = try DatabaseQueue(path: dbFilename)

            try dbQueue.inDatabase({db in
                // テーブルを作る
                var sql = "CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY, name TEXT)"
                try db.execute(sql)

                // データを登録
                sql =  "INSERT INTO test(id, name) VALUES(?, ?)"
                for i in 0..<10 {
                    try db.execute(sql, arguments: [i+1, "hoge" + i.description])
                }
                
                // 検索する
                sql =  "SELECT * FROM test"
                let rows = try Row.fetchCursor(db, sql)
                while let row = try rows.next() {
                    let id:Int? = row.value(named: "id")
                    let name:String? = row.value(named: "name")
                    print("\(id!):\(name!)")
                    
                }
            })
            
        } catch {
            
        }



このエントリーをはてなブックマークに追加

JSONSerializationというクラスがあってこれを使う。
JSONの文字列からオブジェクト(ArrayやDictionary)に変換する。

        let jsonStr = "[ { \"name\":\"山田太郎\", \"age\":22 }, { \"name\":\"山田花子\", \"age\":24 } ]"
        // JSON文字列をNSDataに変換
        let jsonData = jsonStr.data(using: String.Encoding.utf8)
        do {
            // DataからJSONオブジェクトに変換
            let json = try JSONSerialization.jsonObject(with: jsonData!, options: .mutableLeaves) as! Array<Dictionary<String, Any>>
            for item in json {
                if let name = item["name"], let age = item["age"] {
                    print("\(name):\(age)")
                }
            }
        } catch {
        }

オブジェクトをJSON(文字列)に変換する。オブジェクトは、NSArray、NSDirctionaryでその中の値は、NSString、NSNumber、NSDictionary、NSNullでNSDictionaryのキーはNSStringじゃないといけない。

        let json = [
            [ "name":"山田太郎", "age":22 ],
            [ "name":"山田花子", "age":24 ]
        ]
        do {
            if JSONSerialization.isValidJSONObject(json) {  // JSONに変換できるかチェック
                // JSONに変換(.prettyPrintedを指定すると見やすいように改行や空白が挿入される。)
                let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
                // ↓こっちだと空白や改行が含まれない
//                let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
                // Dataを文字列に変換する。
                let jsonStr = String.init(data: jsonData, encoding: .utf8)
                if let str = jsonStr {
                    print(str)
                }
            }
        } catch {
            
        }



このエントリーをはてなブックマークに追加

とりあえず、URLSessionを使って通信してみる。(たぶん一番単純なもの)

macOS向けに書くがiOSでも基本的に同じだ。

ボタンを貼ってそれを押した時の処理をこんな感じにする。

    @IBAction func buttonClick(_ sender: NSButton) {
        let url = URL(string: "http://www.livedoor.com/")
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        let req = URLRequest(url: url!)
        
        let task = session.dataTask(with: req, completionHandler: {
            (data, res, err) in
            if let uerr = err {
                print(uerr.localizedDescription)
            }
            if let udata = data {
                let str = String(data: udata, encoding: String.Encoding.utf8)
                print(str ?? "エラー")
            }
        })
        task.resume()
    }

これを実行するとこんなエラーがでる。

2017-02-07 23:04:07.107 TestHttp[71203:1144451] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

App Transport Security(ATS)によってHTTP通信をブロックしてるって書いてある。基本的にHTTPS通信しろと言うことだ。
例外的にこれを解決するにはInfo.plistを変更する必要がある。何種類か方法があるが何個か書いておく。

非推奨の方法

App Transport Security Settingsを追加してその下にAllow Arbitrary Loadsを追加してYESにする。

002

例外ドメインを追加する方法

App Transport Security SettingsにException Domainsを追加してDictionary型でドメイン(ここではwww.livedoor.com)を追加する。NSTemporaryExceptionAllowsInsecureHTTPLoads、NSIncludesSubdomainsをBoolean型でYESで追加する。

003

次にTextViewに受信したデータを表示してみよう。
UI部品を操作するにはメインスレッドで行う必要があるのだが、dataTaskに指定するクロージャは別スレッドで実行されるのでDispatchQueue.main.asyncを使ってアクセスする。TextViewをはっ付けてtextViewでアクセスできるようにして、次のコードをprint(str ?? "エラー")の次あたりに追加する。

                DispatchQueue.main.async {
                    self.textView.string = str
                }

(追記)
DispatchQueue.main.asyncより、OperationQueue.main.addOperationの方がいいのかな。



このエントリーをはてなブックマークに追加

↑このページのトップヘ