JSON勉強記

スマホ全盛、呼吸するようにTwitterをするという時代、正直、ホームページへのアクセス数など日に数十PVあればいいものです。
そのために日々デザインに凝ることは正直時間と労力の無駄遣いでしょう。

今はむしろ、自身のITスキルの勉強の題材として活用していることも多いです。
社会人1年目の私は、実はある会社で乗換案内のプログラムを作っていたりします。
「KR鉄道館」を運営する中で、HTMLからCSS、JavaScriptくらいは一通り経験していますが、C言語でさえ就職して初めて触ったもの。
なにぶんにもIT技術に関する専門教育を受けてきたわけではないため、実務のためには自分でいろいろ勉強してみる必要があります。

今回はサイトの情報をデータベース管理するため、JSONを導入してみました。
そもそも今ほとんどホームページを更新できていないのですが、たまに更新するときにいつも行っているルーチンワークで、こんな悩みがありました。

  • 更新情報の作成に、細かい作業が多く、煩雑である。
  • 更新情報をトップページと更新情報ページのそれぞれに同一内容を表示させているのに、それぞれ手作業で更新していたため、面倒である。

そこで今回、次のような仕様で、更新作業を簡略化すべく考えました。

  • 更新情報データはデータベース化して、複数のページから同じファイルに情報を呼びにいく。
  • HTMLを自動生成する際、トップページ用と更新情報ページ用で、生成方法を分ける。
  • トップページ用:データベースのうち最新の5件を表示する。
  • 更新情報ページ用:指定された年の情報をすべて表示する。
  • 見た目はJSON導入前後で変化しないよう配慮する。

「てつたのアルバム」も、各アルバム情報(タイトル、キャプション、作成日等)のデータベースを作り、そこから各ページを接続させて構築しているのですが、JSONをまともに知らなかった時分、JavaScriptの配列を使ってこれを実現していました。
しかし、JavaScriptの配列をそのままデータベースとして使うのはあまりスマートとはいえないため、もっときれいに作りたいと考えていました。

そこで今回は、JSONを使ってデータベースを作り、そのデータを基に自動でページ内容が更新できるようにしました。

1.データベースの作成


JSONでデータを作ります。今回はこんな感じにしてみました。

data.json
{
	"data" : [
		{
			"ymd"	:	20170218,
			"mark"	:	"a",
			"url"	:	"album/",
			"text"	:	"「増毛の記憶~2016」ほかアルバム3点を公開しました。"
		},
		{
			"ymd"	:	20160522,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	20160604,
			"mark"	:	"o",
			"url"	:	"link.html",
			"text"	:	"リンク集を更新しました。"
		},
		{
			"ymd"	:	20160529,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	20160405,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	19001231,
			"mark"	:	"m",
			"url"	:	"",
			"text"	:	"JSONテストデータ3"
		},
		{
			"ymd"	:	19001101,
			"mark"	:	"s",
			"url"	:	"",
			"text"	:	"JSONテストデータ2-1"
		},
		{
			"ymd"	:	19001031,
			"mark"	:	"si",
			"url"	:	"",
			"text"	:	"JSONテストデータ2"
		},
		{
			"ymd"	:	19000101,
			"mark"	:	"b",
			"url"	:	"index.html",
			"text"	:	"JSONテストデータ1"
		}
	],
	
	"markdef" : {
		"a" : "アルバム",
		"b" : "BVE",
		"s" : "駅",
		"m" : "動画・音",
		"si": "サイト",
		"o" : "その他"
	}

}

{ }(大かっこ)を使うと連想配列:オブジェクトを作成でき、「"key" : "value"」の形で値が設定できます。
また、[ ](角かっこ)を使うことで、0番から始まる各種プログラム言語でおなじみの配列をつくることができます。

今回はこれを組み合わせて、"data"のキーに各更新情報の配列をつくり、その中にそれぞれオブジェクトを作りました。
"ymd":更新日。データの整理に最も重要。
"mark":行頭のジャンルマーク。
"url":リンク先URL。ルートディレクトリを基準に相対パスで記述しています。
"text":更新情報文の本文。

最初の5件は実際に使うデータ、残りの1900年を指定したデータはテスト用のダミーデータです。

なお、"markdef"キーには、各ジャンルマークの記号に対する日本語名を定義しています。ジャンルマーク画像の代替テキストとして使用します。

2.JavaScriptコードの作成


そして、このJSONを呼び出すために書いたソースがこちらです。

updates.js
// HTTP通信用、共通関数
function createXMLHttpRequest(cbFunc)
{
	var XMLhttpObject = null;
	try{
		XMLhttpObject = new XMLHttpRequest();
	}catch(e){
		try{
			XMLhttpObject = new ActiveXObject("Msxml2.XMLHTTP");
		}catch(e){
			try{
				XMLhttpObject = new ActiveXObject("Microsoft.XMLHTTP");
			}catch(e){
				return null;
			}
		}
	}
	if (XMLhttpObject) XMLhttpObject.onreadystatechange = cbFunc;	//ファイルの読み込み完了時の動作
	return XMLhttpObject;
}

// document.getElementById
function $(tagId)
{
	return document.getElementById(tagId);
}

function writeData(position, mode)	//ファイル名、表示するID、動作モード
{
	fName = 'updates/data.json'
	httpObj = createXMLHttpRequest(function(){displayData(position, mode)});	//クロージャにすると引数を収められる
	if (httpObj)
	{
		//リクエストのタイプを設定
		httpObj.open("GET", fName, true);
		//キャッシュは読みに行かせない
		httpObj.setRequestHeader('Pragma', 'no-cache');   
		httpObj.setRequestHeader('Cache-Control', 'no-cache');                    
		httpObj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 00:00:00 GMT');
		//リクエストを送信
		httpObj.send();
	}
}
function displayData(position, mode)
{
	if ((httpObj.readyState == 4) && (httpObj.status == 200))	//読み込み完了
	{
		$(position).innerHTML = parseJSON(httpObj.responseText, mode);
	}
}
// JSONのデータを解析して表示
function parseJSON(jsData, mode)
{
	var data = JSON.parse(jsData);
	var resultData = "";
	for(var i=0; i<data.data.length; i++)
	{
		//データを変数に収める
		var ymd		= 	data.data[i].ymd;	// 日付
		var mark	= 	data.data[i].mark;	// マーク記号
		var url		= 	data.data[i].url;	// URL
		var text	=	data.data[i].text;	// 情報内容
		
		var hit = false;
		
		if(mode >= 1900){	//年指定モード
			if(Math.floor(ymd / 10000) == mode){
				hit = true;
			}
		}
		else{				//表示数指定モード
			if(i < mode){
				hit = true;
			}
			else{
				break;
			}

		}
		
		if(hit){
			var showymd = (("0" + Math.floor(ymd / 10000) % 100).slice(-2)) + '.' + Math.floor(ymd / 100) % 100 + '.' + ymd % 100;
			resultData += '<p><img src="m_' + mark + '.gif" width="50" height="15" alt="' + data.markdef[mark] + '" class="umark">'
					+ showymd + ' ';
			
			//URL指定がないときはリンクを外す
			if(url != ""){
				resultData += '<a href="' + url + '">';
			}
			
			resultData += text;
			
			if(url != ""){
				resultData += '</a>';
			}
			
			resultData += '</p>';
		}
	}
	return resultData;
}



ページには次のようにしてコードを埋めました。

(<head>~</head>内)
<script type="text/javascript" src="updates/updates.js"></script>

(トップページ:<body>~</body>内)
<div id = "jsondata"></div>
<!-- JSON化 2017.2.18 -->
<script type="text/javascript">
	writeData('jsondata', 5)
</script>

(更新情報ページ:<body>~</body>内)
<div id="u_body2">
</div>
<script type="text/javascript">
	writeData('u_body2', 2017)
</script>

各ページから、writeData関数で指定したIDの位置に情報を出力します。
引数として、第一引数に出力先のID、第二引数に出力モードを設定しました。
第二引数の出力モードは、1900以上の時はその年の全データを出力、1900未満の時は最新のデータから指定した件数のデータを出力させることとしました。

writeData関数から呼び出すcreateXMLHttpRequest()関数で、まずAjaxのXMLHttpRequestオブジェクトを作成します。
このとき、引数に、JSONファイル(data.json)の読み込みが終了したときに行う処理を記載するのですが、関数を記載する際、そのまま「関数(引数)」と記述すると、指定した関数の実行前に引数の内容が評価され実行されてしまいます。
そうではなくて、ちゃんと必要な時にその引数を伴って関数が実行できるようにするために、クロージャの形を使って、処理させたい関数をもう一度"function(){}"の形で包んであげると、中身を実行させないで引数として渡すことができました(31行目)。

無事にXMLHttpRequestオブジェクトが作成できれば、このオブジェクトのhttpObj.onreadystatechangeの中に先の関数名を埋め込みます(18行目)。

ブラウザはJSONデータについて、結構キャッシュを利用してしまいます。
更新情報は常に最新のものを使用したいので、ブラウザのキャッシュは使用せず、都度ファイルを読みにいくように設定しています(37~39行目)。

さて、data.jsonが読み込まれると、関数displayData()が実行されます。
onreadystatechangeはreadystateが変化するたびに呼び出されますが、
readystate=4、status=200のときがロード成功を指すそうなので、このときに関数parseJSON()を呼びます。
この第一引数のhttpObj.responseTextに、data.jsonの文字列が入っています。

まず54行目で、eval()関数JSON.parse()がdata.jsonの内容を解釈してJavaScriptで使うオブジェクトの形に変換します。
「この関数一つでJSONを解釈できる、だからとても扱いやすい!」が標榜されているのですが、JSONの記述法は結構厳しめで、ここでちゃんとエラーなく変換できるまでに時間がかかりました。
現在eval()関数は推奨されていないということで、記法を訂正しました。ご指摘いただきました竹麻呂さま、ありがとうございました。(2/19 4:30)

更新情報データの一つ一つがオブジェクトとその配列で構成されているので、for文をぶん回して項目ごとに内容を解釈していきます(59~62行目)。
ここでやっと、HTMLから引き継いできた引数modeを使います。
modeが1900以上なら年指定モードとみなし、指定した年のデータのみを使うように処理します。
また、modeがそれ未満なら表示数指定モードとし、ループカウンタ変数iの値を利用して指定個数だけデータを抽出します。

抽出したデータだけを変数resultDataに蓄積して返り値としてリターンします。
$(position).innerHTMLを使って、positionに指定したIDの位置にデータを書き出します。
document.getElementByldという長ったらしいオブジェクト名を省略するために、$()という関数の形に括って出力しているそう。jQueryでよく使う記法らしいです。

こうして一日かけて更新情報データベースのJSON化が完成しました。
実際のところ、この工数にペイできるほど今後の更新があるのか未知数ですが(笑)、現在様々な分野で導入が進むJSONを学ぶいい機会になったと思います。

ITは目的ではなく手段でなければなりませんので、やりたいことを確実に実現させる方法として、必要なものはこれからも吸収していきたいと思っています。

参考文献



祝、カープ優勝。

広島東洋カープ、25年ぶりリーグ優勝おめでとうございます!

ここ数年調子が上がっていましたが、今年私が観戦した3試合はすべて敗北。
むしろ運がよいと言われました。

生まれて初めての優勝ともあり大変興奮しております。

ここまで来れたのも、ひとえに広島の力。
みんなの思いが実ってきょうを迎えられたのでしょうね。

まずはお祝いを。


日本のドライバーに関する所感


米大統領予備選。
アメリカ式のジョークを日本語字幕にするとどうしてマヌケな印象が抜けないのでしょうかw
でも「政治ネタ」の会話をタブーにする日本より全然マシな国だと思いますよ。



久しぶりに、長距離のドライブをしてきました。

とあるレンタカー店でデミオのMT車があることを知り、予約。当日出会ったその車はなんと昨年11月に納車されたばかりの最新4代目でした。
発進操作でアイドリングストップ機能と悪戦苦闘しながら1,000kmあまり。北は富山県五箇山から南は和歌山潮岬まで、青空の下もドカ雪の中も走り抜けました。

さてさて、私が単純に免許歴約2年、運転が下手だからかもしれませんが、こう時々長距離のドライブをしていて、しばしば周囲の交通状況について怖い目に遭っています。その中で感じた、「日本のドライバーに対して思う所感」を、いくつか述べたいと思います。


1.とらない車間

車間距離がとにかく短い。追突したら誰が責任をとるのか、と思わんばかり。
高速道路を走行する場合、一般に乾燥路面で100km/h走行時に100mの車間距離を要するとされています。急に前車が停止した場合に安全に停止できる距離、すなわちその速度で走行したときの停止距離に相当します。
しかし実際に走ってみると、とにかく車間をとらないとらない。前の車に速度を煽る目的なのか何か知りませんがとにかく車間を詰める。
本当なら、後ろの車が車間距離を詰めてくるのであれば、追突されないように車間距離に応じてこちらも減速しなければなりませんから、車間を詰めて煽る行為はむしろ逆効果をもたらすということ、ちょっと考えればわかりませんかね。

関連してなのですが、上り勾配で停車時にものすごくひっついて止まる車ありますよね。みんなAT車だと思っている。
しかし、発進前にちょっと退行してしまう可能性を考えて上り勾配では少し離して止まるのも常識ではないでしょうかねぇ?せめて1mは距離が欲しいです。


2.カーブで減速しない

見通し不良区間で速度が出すぎる。そして私が安全な速度で運転しようとするとまた周囲に煽られる。
前方を見通せない範囲にはどんな危険があるとも知れないから、見えない場所に至る前に停止できる距離、つまり「見通し可能な距離>停止距離」で走ることは自動車運転の常識ではないでしょうか…この不等式が逆転することが許されるのは専用通路を設けた鉄道だけですw
さらに雪道のような滑りやすい道では極力曲線通過中に制動せず走行するため、手前の直線で十分減速する必要があります。そういった「安全のための運転」を、きちんと受け入れていただきたいと思います。


3.車線の使い方が酷い

同一方向に複数の車両通行帯があるとき、一番右の車線は何に使うのでしょうか…?
追越車線、ですよね?
なんだかどの道を走っていても同じような速度で車が走っており、その車線の意味を成していません。追越車線を自分のペースでちんたらと走り続けている車さえ見かけます。
東京の幹線道路のように、車線をフルに使わなければ交通量をさばけないような場合はいささか仕方がありません。しかし左の走行車線で十分余裕がある場合でさえこの追越車線が普通の車線と同様に扱われている状態に疑問を感じます。聞いたところでは、ドイツのアウトバーンではこのような光景は全く見られないそうです。



ドライブにおいてもっとも心地よいのは、自分のペースで安全に運転できることでずが、もちろん他者の気持ちを考えてストレスを与えないようにすることも当然必要です。
しかし、法や安全を考慮した運転さえも嫌な目をされなければいけないのも、どうかと思います。

警察の取り締まりも、安全性に直結しない場所でのネズミ捕りではなくて、車線違反や無灯火など、事故に直結しかねない危険な運転すなわち「事故の芽」を重点的に扱っていく姿勢を作ってほしいと思います。

より安全な日本の道路を目指して、人口減少とともに自動車学校の市場規模の縮小はすでに非可逆の趨勢ではありますが、運転教育者にはより一層の安全重視の教育を求めたいものです。

テーマ:思うこと - ジャンル:学問・文化・芸術

戯言

今年2016年は、小学2年次、私がKR鉄道館の前身となるホームページを立ち上げてから15年にあたります。
また、2011年にTwitterアカウントを持ってから数えても、はや5年となります。

比較的早い段階でネットに飛び込み、その世界を見てきた人間としては、その世界の日進月歩ぶりが逍遥感をも覚える今日この頃です。

しかし、ここまでたくさんの情報に、瞬間的かつ大量に接することができるようになって、本当に暮らしは豊かになったといえるのか。…そんな哲学的議論は様々な分野ですでになされていることと思いますが、ここでは「鉄道趣味界」にスポットを当てて考えてみます。

パソコンやスマートフォンなどが若年層に至るまで広く普及し、行動力が特に活発な若い鉄道ファンにとっては、最新の鉄道情報をそれこそ「いつでも・どこでも」入手できる環境を手に入れたことにになります。
それゆえ、日々噴き出す新しい情報に対して常に敏感になり、機敏な行動をとれるようになったことは言うまでもありません。

しかし、それによって、所謂「撮影地探し」あるいは「葬式鉄」などといった趣味行動が、以前にも増して加速してしまったのではないでしょうか。
「○○がなくなる。みんなで見に、撮影しにいこう」そういった動きが、Twitterのタイムラインを通じて広く伝わり、大きな「鉄界の世論」となって駆けまわります。
するといつの間にか、「これは絶対に撮りに行かなければならない」といった義務感に苛まれるようになり、自分を見失ってしまった人が、少なくないように思います。

一般にインターネットは、マス・コミュニケーションがあまり持ちえなかった一般人の世論を簡単に世界に発信する環境を具備したことから、個人主義を加速する道具になったとされます。しかし実際のところは、「○○しなければならない」という認識を大きく広め、集団行動の激化をもたらしたのではないでしょうか。
同じことは、旅行やグルメの口コミサイトにも言えることです。今までにはなかった方法で、実際にその地を訪ねた人々の情報が集まり、統計化され、ランキング付けがなされる。すると評価の高い物件だけに特に注目が集まり、そこに人が集中する。…鉄道に限らず、あらゆることについて最近見ていて思うのは、インターネットがかえって、行動の集団化・大衆化を引き起こしたということです。

皆が同じことを繰り返したところで、そこに「個」が輝くことはありません。
人と同じ行動をとるだけでは、人を超えることはできない。そんなことをどこかの偉人は語っていたような気がします。

ネットによって多くの情報を仕入れられるようになったからこそ、その中で必要な情報を手に入れて、「自分」をしっかりと持ちましょう。
そして、しっかりと自分の意見・「したいこと」を持ち、もし鉄道撮影に勤しむ身であれば、写真をきちんと「コミュニケーションツール」として捉えたいもの。写真は数多の伝達メディアのひとつであり、写真は何かを「伝える」ものでなくてはならないと思います。

日々ファインダーを通じて世界をみるとき、今までの人生で蓄積してきたものを土台にして、自分なりに世界をみつめ、それを伝えよう、そういった気持ちでおりたいものです。


12枚の写真で振り返る2015年

…こういう企画をいままでやったことがなかった私ですが、
大晦日にちょっと一息いれながら、今年を写真でまとめてみたいと思います。


Miyajima Matsudai ferry

1月…吹雪の宮島

瀬戸内とはもともと降水量の少ない土地であるはずが、正月2日はにわか雪に降られる空模様となった。
突然の吹雪に打たれて急ぎ足で船に乗り込む、まるで青森の連絡船のような雰囲気に…


Twilight Express

2月…黄金列車よさらば

大阪札幌間を結んでいた豪華寝台特急「トワイライトエクスプレス」が3月に引退。
2015年、2016年と、定期急行列車、定期寝台列車、定期客車列車が次々と姿を消し、
日本の鉄道史は一区切りを迎えたといっても過言ではない。


Ueno-Tokyo line debut

3月…上野東京ライン開業

東北線列車が名実ともに東京駅発着を果たしたその日、東北・高崎・常磐線~東海道・横須賀線を、新宿と東京の2大ターミナル駅それぞれを経由して結ぶ巨大直通ネットワークが完成した。


Oyama Cable Car

4月…山の漢の勇退

大山ケーブルカーの車両が、投入50年の節目となる今年リニューアルされた。
新しいケーブルカーの導入にあたって、蓄電池を導入し途中区間の架線を廃すなど、大山ケーブルは大変貌を遂げる。
信仰の山の新しい歴史が始まった。


Kiseki no Ippon-matsu (the miracle pine)

5月…奇跡の一本松

陸前高田市の「奇跡の一本松」を初訪問。
松はすでに塩害等の影響により壊死してしまったため、保存処置を施された状態で初めて訪れることになったが、
自然の力強さから「負けない」という強い教訓をくれることは間違いないだろう。
早くも来年には、震災から5年を迎える…


Mizumoto Park

6月…あじさい

就職活動も忙しさを増し、気休めの外出程度になってきたこのころ。
気候変動の影響か、ここ数年美しい紫陽花に出会っていないが、その中でもここ水元公園で見た紫陽花は、久しぶりに「きれいだ」と感じたものであった。


Enoshima Summer

7月…夏が来た

面接や説明会ついでにシャッターを切るのが数少ない楽しみになってきたこの頃。
この江ノ電も、スーツを着ながら撮影したものである。
汗だくになりながらも、撮りたいものを自分の切り口で撮るという愉しみは尽きることがない。


Sendai Tanabata Festival

8月…七夕祭り

ある採用選考が岩手県で行われたため、新幹線を使って日帰りすることになった。
ただ往復するのはどうしても自分の気が許さないので、丁度仙台で七夕祭りが開催中だったこともあり、帰路途中下車してみることにした。
ちょうど同じ夜、青葉城址では高校の同級生が在籍している合唱団が演奏しており、彼との久しぶりの再開をも果たすことができた。


Departure

9月…Departure

明日への出発。
離陸の3分は特に緊張が走る時間だという。
出発は、最初が肝心だと教えてくれた。
…わたしも頑張らなければ。


Oga in Fall - 男鹿の秋風

10月…男鹿の秋風

一台のマーチを3日間乗り回し、秋田県を一周。
男鹿は実りの秋を迎えていた。
半島のシンボル、寒風山と。


Arashiyama

11月…嵐山

天龍寺の竹林ともみじを。
しっとり、静かに。
秋の京都はわたし自身の毎年恒例となってきた。


Tsuchitaru station

12月…トンネルを抜けると

国境の長いトンネルを抜けると雪国であった。
今年は暖冬傾向で東京の銀杏は落葉が済まないまま年越しを迎えそう。
しかし国境を越え越後の国へ足を踏み入れると、そこには銀世界が広がっていた。



今年は「鉄道」をテーマにした写真を撮影することが大変少なくなりました。
それには自身の身の回りの状況の変化も大きいのですが、その一方で、様々な物事にアンテナを張ることになったことで、
「量より質」の写真を目指そうと思うようになった心情の変化もあるように思います。

いよいよ2016年、学生から社会人へとわたし自身における重要な転機を迎えることになります。
最初が肝心。明日の自分の糧のために、これからもいろいろなものを吸収して、自らを鍛えていきたいと思います。


皆様にとっても、くる年が良い年でありますように。



プロフィール

てつた

Author:てつた
KR鉄道館

元駅員さん。
社会人2年目の、法学部卒
へっぽこ新米プログラマー。
たまには旅に出たい。

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
最新記事
最新コメント
最新トラックバック
カテゴリ
月別アーカイブ
検索フォーム
RSSリンクの表示
リンク
QRコード
QR