[雑記]グンマーは空に浮いていない。

グンマーは空に浮いているって言われるけれど。。。
グンマーはラピュタのように空に浮いていません。関東地方を大雪が降ったりなど天気が荒れるときに「グンマーは空に浮いているから関係ないよね(キリッ」とかツイッターでつぶやかれたり、定期的にまとめサイトにスレが上がったりしていますがそれはちがいます。
マジレスすると、グンマーの空には戦闘機やら航空機やらヘリコプターが飛び交っています。グンマーが空に浮いていたら飛行機やヘリはグンマーの上空を飛べないと思うの。

昔は飛行機やヘリなんて珍しかった。
僕は前橋市で育ちましたが、僕ががきんちょの頃(20年くらい前)は、航空機やヘリやらって珍しかったと思うんです。何故に、グンマーには空港やら港やらないのに騒がしいのでしょうか。今日もすごくうるさい。自衛隊のヘリがどっかに向かっているのではなく旋回しているようなので訓練なのか。。。

マジでうるさい。
イデオロギーやら集団的自衛権やら北朝鮮のミサイル問題は抜きにして、住宅地の上空を飛ばれると航空機やヘリの音は非常にうるさく、家の壁は振動し、犬は吠え、いいことはありません。グンマーはあまりオスプレイやらなんやらで盛り上がりませんが、グンマーって馬鹿にされながらも、ちょっと我慢している人たちが居るっているのをわかってほしいな。
gunma01

[Node.js]LINQを使って要素を列挙して表示する。

for文使わないで列挙する。
npm linq(linq.js)を使って、要素の表示(ダンプ)は簡単に出来ます。

ベースソース

var Enumerable = require('linq');

var a = "{\"tag\" : \"aaa\" , \"res\" : [{\"key\":\"val1\"},{\"key\":\"val2\"},{\"key\":\"val3\"}]}";
var b = "{\"tag\" : \"bbb\" , \"res\" : [{\"key\":\"val2\"},{\"key\":\"val1\"},{\"key\":\"val4\"}]}";

var json_a = JSON.parse(a);
var json_b = JSON.parse(b);
var list = json_a.res.concat( json_b.res );

連想配列listに対してLINQを実行する。

◇WriteLine()のみ

Enumerable.From(list).WriteLine();

実行結果

{ key: 'val1' }
{ key: 'val2' }
{ key: 'val3' }
{ key: 'val2' }
{ key: 'val1' }
{ key: 'val4' }

◇列挙要素の指定

Enumerable.From(list).WriteLine("$.key");

実行結果

val1
val2
val3
val2
val1
val4

◇要素を並び替えて列挙

Enumerable.From(list).OrderBy("$.key").WriteLine("$.key");

実行結果

val1
val1
val2
val2
val3
val4

[Node.js]Node.jsでLINQしてみる。

npm linqパッケージの使用。
LINQ坊なので、Node.js内でLINQ(Language Integrated Query)を使用してみたいと思います。

linq – linq.js – LINQ for JavaScript library packaged for node.js
https://github.com/mihaifm/linq
これってneue.ccさんのlinq.jsをNode.js用に移植したものだったんですねー。

ということで、linqのtutorial.jsを眺めていてもなとなくわかるのですが、本家linq.jsをダウンロードして、reference.htmを実行してみると色々サンプルが載っているので参考にしてみてください。

とりあえず、個人的によく使う、Select,Where,Take,Skip,Any,Countについてのみ。
前回のエントリーで使用したRSSフィードをJSON化したものに対して、LINQ操作をしてみたいと思います。
RSS(2.0)フィードはrss-channel-itemノードが配列になっているので、この配列をベース(From)にしてLINQ操作を行います。

ベースソース

var Enumerable = require('linq');

var request = require('request');
var url = 'http://kimux.net/?feed=rss2';

request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var json = xml2json(body);
        /*
        jsonに対してLINQ操作
        */
    }
});

function xml2json(body) {
    return JSON.parse(require('xml2json').toJson(body));
}       

Select 1

        // Select - すべての記事のタイトルを列挙 ①
        console.log("\nSelect 1 - ");
        Enumerable.From(json.rss.channel.item)
            .Select("$.title")
            .WriteLine();

Selectにはイテレータ($)を使って要素にアクセスし目的のプロパティを取り出すやり方が基本形なのかな。

Select 2

        // Select - すべての記事のタイトルを列挙 ②
        console.log("\nSelect 2 - ");
        var titles = 
            Enumerable.From(json.rss.channel.item)
                .Select("$.title");
        titles.ForEach("console.log($)");

Selectの戻りは単純に要素の配列ではなくEnumerableとなっているので、継続してLINQ操作をすることができます。

Select 3

        // Select - すべての記事のタイトルを列挙 ③
        console.log("\nSelect 3 - ");
        Enumerable.From(json.rss.channel.item)
            .WriteLine("$.title");

単に表示させるだけならWriteLineに表示する要素を指定することも可能。
Select1,2,3 実行画面

Select 1 2 3 -
[Node.js]XMLをJSONに変換して操作する。
[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[上原ひろみ]オフィシャル スマートフォンサイトオープン!
[雑記]Windows8は普及するのか。
[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
[PC]VMware Player 5でUbuntuを手動インストールする方法。
[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

Select 4

        // Select - すべての記事のタイトルを列挙 ④
        console.log("\nSelect 4 - ");
        Enumerable.From(json.rss.channel.item)
            .Select(function(value, index){
                return index + ":" + value.title;
            })
            .WriteLine();

indexを知ることも可。これは.Netよりも楽。
Select4 実行画面

Select 4 -
0:[Node.js]XMLをJSONに変換して操作する。
1:[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
2:[雑記]Nortonさんの延長画面がソレっぽく見える件。
3:[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
4:[上原ひろみ]オフィシャル スマートフォンサイトオープン!
5:[雑記]Windows8は普及するのか。
6:[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
7:[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
8:[PC]VMware Player 5でUbuntuを手動インストールする方法。
9:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

Where

        // Where - タイトルに"雑記"を含む記事を表示
        console.log("\nWhere - ");
        Enumerable
            .From(json.rss.channel.item)
            .Where("$.title.indexOf('雑記') != -1")
            .Select("$.title")
            .WriteLine();

functionを使用することもできるけどイテレータを使うのが簡単で分かりやすい。
Where 実行画面

Where -
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[雑記]Windows8は普及するのか。

ちなみに、次の様な書き方も出来る。

        // Where - タイトルに"雑記"を含む記事を表示
        console.log("\nWhere - ");
        Enumerable
            .From(json.rss.channel.item)
            .Where("p=>p.title.indexOf('雑記') != -1")
            .Select("$.title")
            .WriteLine();

Count

        // Count - タイトルに"雑記"を含む記事の件数
        console.log("\nCount - ");
        var cnt = 
            Enumerable
                .From(json.rss.channel.item)
                .Count("$.title.indexOf('雑記') != -1");
        console.log("Count = " + cnt);

LINQはWhereを使用しないで、Countに直接条件を書くことができます。
Count 実行画面

Count -
Count = 3

Any

        // Any - タイトルに"雑記"を含む記事の有無
        console.log("\nAny - ");
        var any = 
            Enumerable
                .From(json.rss.channel.item)
                .Where("$.title.indexOf('雑記') != -1")
                .Any();
        console.log("Any = " + any);

Any 実行画面

Any -
Any = true

Take

        // Take - 最新記事2件のタイトルを表示
        console.log("\nTake - ");
        Enumerable
            .From(json.rss.channel.item)
            .Take(2)
            .Select(function(value, index){
                return index + ":" + value.title;
            })
            .WriteLine();

Take 実行画面

Take -
0:[Node.js]XMLをJSONに変換して操作する。
1:[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。

Skip

        // Skip - 最新記事2件目以降のタイトルを表示
        console.log("\nSkip - ");
        Enumerable
            .From(json.rss.channel.item)
            .Skip(2)
            .Select("$.title")
            .WriteLine();

Skip 実行結果

Skip -
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[上原ひろみ]オフィシャル スマートフォンサイトオープン!
[雑記]Windows8は普及するのか。
[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
[PC]VMware Player 5でUbuntuを手動インストールする方法。
[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

まとめ
.NetFrameworkのLINQを知っていれば、すぐにマスターできるのでは。LINQを使えばループと条件分岐を大幅に減らすことができるのでコードが短く書けますしね。

[Node.js]XMLをJSONに変換して操作する。

RSSフィード(XML)をJSON化して操作してみる。
Node.jsでXMLをJSONに変換して読み込ませてみます。

使用環境は次の通り。
Node.js version v0.8.16
npm request   // httpリクエスト用
npm xml2json // XML->JSON変換用

RSSフィードを取得して、記事タイトルと投稿日時を表示する。
本サイトのRSSフィードをhttpリクエストで取得し、XMLをJSONに変換後、記事のタイトルと投稿日時を列挙させてみます。

RSSフィード(RSS2.0)の一部

<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
<channel>
<title>Kimux.Net</title>
<atom:link href="http://kimux.net/?feed=rss2" rel="self" type="application/rss+xml"/>
<link>http://kimux.net</link>
<description>プログラムと趣味と。</description>
<lastBuildDate>Wed, 10 Apr 2013 01:12:51 +0000</lastBuildDate>
<language>ja</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>http://wordpress.org/?v=3.5.1</generator>
<item>
<title>[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。</title>
<link>http://kimux.net/?p=1238</link>
<comments>http://kimux.net/?p=1238#comments</comments>
<pubDate>Mon, 08 Apr 2013 08:32:35 +0000</pubDate>
<dc:creator>m-kimura</dc:creator>
<category>
<![CDATA[ C# ]]>
</category>
<category>
<![CDATA[ プログラム ]]>
</category>
<guid isPermaLink="false">http://kimux.net/?p=1238</guid>
<description>
<![CDATA[
Webサービスが提供するWebAPIからJSON形式で情報をもらう。 今やWebAPIなどの受け渡しに使うのはJSONが当たり前になっています。 そこで、C#でWebAPIなどからJSON形式の文字列を受信した時の扱いに &#8230; <a href="http://kimux.net/?p=1238">続きを読む <span class="meta-nav">&#8594;</span></a>
]]>
</description>
<content:encoded>

getRss.js

var request = require('request');
var url = 'http://kimux.net/?feed=rss2';

request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var json = xml2json(body);

        for (var i in json.rss.channel.item) {
            console.log("title:" + json.rss.channel.item[i].title);
            console.log("date :" + json.rss.channel.item[i].pubDate);
        }
    }
});

function xml2json(body) {
    return JSON.parse(require('xml2json').toJson(body));
}

実行結果

$ node getRss.js
title:[C&amp;#35;]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
date :Mon, 08 Apr 2013 08:32:35 +0000
title:[雑記]Nortonさんの延長画面がソレっぽく見える件。
date :Tue, 02 Apr 2013 17:04:40 +0000
title:[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
date :Sat, 30 Mar 2013 18:59:47 +0000
title:[上原ひろみ]オフィシャル スマートフォンサイトオープン!
date :Fri, 29 Mar 2013 11:30:36 +0000
title:[雑記]Windows8は普及するのか。
date :Thu, 28 Mar 2013 06:36:38 +0000
title:[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
date :Sat, 23 Mar 2013 16:48:40 +0000
title:[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
date :Fri, 22 Mar 2013 06:21:02 +0000
title:[PC]VMware Player 5でUbuntuを手動インストールする方法。
date :Fri, 22 Mar 2013 04:27:16 +0000
title:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。
date :Thu, 21 Mar 2013 15:30:10 +0000
title:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その2。
date :Tue, 19 Mar 2013 15:09:11 +0000

XMLの属性と要素はJSONに変換するとどうなるのか。
属性値と要素が含まれるXMLをxml2jsonでJSONに変換すると、ノードの最後に要素が格納されます。

JSON変換後の一部。

{"rss":
    {
        "version":2,
        "xmlns:content":"http://purl.org/rss/1.0/modules/content/",
        "xmlns:wfw":"http://wellformedweb.org/CommentAPI/",
        "xmlns:dc":"http://purl.org/dc/elements/1.1/",
        "xmlns:atom":"http://www.w3.org/2005/Atom",
        "xmlns:sy":"http://purl.org/rss/1.0/modules/syndication/",
        "xmlns:slash":"http://purl.org/rss/1.0/modules/slash/",
        "channel":
            {"title":"Kimux.Net","atom:link":{"href":"http://kimux.net/?feed=rss2","rel":"self","type":"application/rss+xml"},"link":"http://kimux.net","description":"プログラムと趣味と。","lastBuildDate":"Wed, 10 Apr 2013 01:12:51 +0000","language":"ja","sy:updatePeriod":"hourly","sy:updateFrequency":1,"generator":"http://wordpress.org/?v=3.5.1",
    

XMLパースが面倒だったので、なんかJSONにしたら楽なのかなぁって思ったから、ちょっと試してみたけど、マジ楽だったw

[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。

Webサービスが提供するWebAPIからJSON形式で情報をもらう。
今やWebAPIなどの受け渡しに使うのはJSONが当たり前になっています。
そこで、C#でWebAPIなどからJSON形式の文字列を受信した時の扱いについてメモ。JSONの扱いにはJSON.Netを使用します。
ここでは、JSON.Netを使用してJSON文字列を連想配列により操作する方法とユーザー定義(クラス定義)に置き換える方法を試します。

JSON.Net
http://json.codeplex.com/

実際のWebサービスを使って試す。
HeartRailsExpressのWebAPIを使用して全国の鉄道情報をJSONで受け取り、C#フォームアプリケーションで使用したいと思います。

HeartRailsExpress – API
http://express.heartrails.com/api.html

今回使用するAPIは、
都道府県情報取得 API,路線情報取得 API,駅情報取得 APIの3つです。

やりたいこと。
・全国の路線、駅情報を提供するWebAPIからJSONを取得。
・WebAPIを使用して、都道府県名の列挙。
・WebAPIを使用して、都道府県別の路線情報の列挙。
・WebAPIを使用して、路線情報から駅情報の取得。
・駅情報を利用して地図上に位置を表示する。

実行画面

※このアプリケーションでは取得したJSON文字列とJSON文字列から生成したXML(XDocument)をTextBoxにそれぞれ表示しています。

連想配列によるデータの操作。
JSONの連想配列によるデータの操作はJSON.Netのデシリアライズ関数(JsonConvert.DeserializeObject関数)にNewtonsoft.Json.Linq.JContainer型を返すように指定します。

◇都道府県名の列挙。路線情報の列挙。
都道府県情報APIは次のJSONを返します。

{
    "response" : {
        "prefecture" : ["北海道","青森県",・・・,"沖縄県"]
    }
}       

JSON.Netを使ってNewtonsoft.Json.Linq.JContainer型に変換しリストボックスに表示します。
※argにはWebAPIから取得したJSON文字列が入っています。

                    var jobj = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(arg);
                    listBoxKen.Items.AddRange(jobj["response"]["prefecture"].ToArray());

路線情報は都道府県名の列挙を行うやりかたと同じです。

                    var jobj = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(arg);
                    listBoxRosen.Items.AddRange(jobj["response"]["line"].ToArray());

◇駅情報の列挙。
駅情報には緯度経度、前の駅名、次の駅名など様々な情報が含まれます。

{
    "response" : {
        "station" : [
             {"x":139.738535,"next":"大崎","prev":"田町","y":35.628135,"line":"JR山手線","postal":"1080075","name":"品川","prefecture":"東京都"},
             {"x":139.728246,"next":"五反田","prev":"品川","y":35.61994,"line":"JR山手線","postal":"1410032","name":"大崎","prefecture":"東京都"}
        ]
    }
}       

駅情報の中から駅名(name)だけを列挙し、リストボックスに表示します。

                    var jobj = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JContainer>(arg);
                    listBoxEki.Items.AddRange(jobj["response"]["station"].Select(p=>p["name"]).ToArray());

ユーザー定義(クラス定義)によるデータの操作。
JSON文字列をユーザー定義型に変換するにはクラス定義が必要になります。クラスを定義する際の注意すべきことはJSONのキーとクラスのプロパティ名が完全一致、JSONの値とクラスの型が変換可能である、ということが重要です。

◇クラス定義

    class MyJsonFormat
    {
        /// <summary>
        /// 都道府県情報
        /// </summary>
        public class PrefectureResponse
        {
            public class Prefecture
            {
                public string[] prefecture { get; set; }
                public Prefecture()
                {
                    prefecture = new string[] { };
                }
            }
            public Prefecture response { get; set; }

            public PrefectureResponse()
            {
                response = new Prefecture();
            }
        }

        /// <summary>
        /// 路線情報
        /// </summary>
        public class LineResponse
        {
            public class Line
            {
                public string[] line { get; set; }
                public Line()
                {
                    line = new string[] { };
                }
            }

            public Line response { get; set; }
            public LineResponse()
            {
                response = new Line();
            }
        }

        /// <summary>
        /// 駅情報
        /// </summary>
        public class StationResponse
        {
            public class Station
            {
                public double x{get;set;}
                public string next{get;set;}
                public string prev{get;set;}
                public double y { get; set; }
                public string line { get; set; }
                public string postal { get; set; }
                public string name { get; set; }
                public string prefecture { get; set; }

                public Station()
                {
                    x = y = 0;
                    next = prev = line = postal = name = prefecture = "";
                }
            }

            public class Stations
            {
                public Station[] station { get; set; }

                public Stations()
                {
                    station = new Station[] { };
                }
            }

            public Stations response { get; set; }

            public StationResponse()
            {
                response = new Stations();
            }
        }
    }

◇都道府県名の列挙。路線情報の列挙。
JSON.Netのデシリアライズ関数に定義したPrefectureResponseクラスを指定します。PrefectureResponseクラスのインスタンスから都道府県名(prefecture)を取り出し、リストボックスに表示します。

                    var jobj = JsonConvert.DeserializeObject<MyJsonFormat.PrefectureResponse>(arg);
                    listBoxKen.Items.AddRange(jobj.response.prefecture);

路線情報の列挙もJSONをLineResponseクラスへと変換し、路線名をリストボックスに表示します。

                    var jobj = JsonConvert.DeserializeObject<MyJsonFormat.LineResponse>(arg);
                    listBoxRosen.Items.AddRange(jobj.response.line);

◇駅情報の列挙。
駅情報の列挙もJSONをStationResponseクラスへと変換し、駅名(name)を取り出してリストボックスに表示します。

                    var jobj = JsonConvert.DeserializeObject<MyJsonFormat.StationResponse>(arg);
                    listBoxEki.Items.AddRange(jobj.response.station.Select(p => p.name).ToArray());

後のことを考えるなら、クラス定義を使用したほうがよい。
その場限りのコードであればわざわざクラス定義を書く必要性が無いかもしれませんが、ユーザー定義型に変換してしまったほうがデータの扱いが後々楽になります。

今回作成したソースはこちら