今回から少し簡潔に書いていきたいと思います。
わからないところは適宜検索したり、参考書などを見たり、質問したりしてください。
第1回で取得したのは1つの長いテキストデータだったので
今回はこれを分解します。
TwitterはXML形式とJSON形式で取得でき、前回はXML形式で取得しましたが、
Search APIとかはXML形式に対応してないので、今回からJSON形式にします。
まず前回のコードのURLの語尾を.jsonに換えて再実行してみてくだだい。
string url = "http://twitter.com/statuses/user_timeline/yuki1090.json";
すると同じようなデータが異なるフォーマットで得られたと思います。
適当に改行とインデントを入れると次のようになります。
[ {"truncated":false, "created_at":"Mon Jan 11 15:26:14 +0000 2010", ・・・略・・・ "user":{ "profile_background_color":"1A1B1F", ・・・略・・・ "screen_name":"yuki1090", ・・・略・・・ }, ・・・略・・・ "text":"つぶやいた内容のUnicode文字列(読めない)" }, {"truncated":false, ・・・以下略
{}で囲まれたところが一つのオブジェクトです。
つまり
[
{つぶやき
{つぶやいたユーザ情報}
}
,
{次のつぶやき
{つぶやいたユーザ情報}
}
, ・・・以下繰り返し
の構造になっていることがわかります。
これをクラスで表現します。
前準備として、プロジェクトの「参照設定」を右クリックして、「参照の追加」→「.Netタブ」
・System.ServiceModel.Web
・System.Runtime.Serialization
を追加します。
※Webの方が選択肢に出ない場合は、プロジェクトのプロパティで
対象のフレームワークがClientProfileになっていないか確認してください。
ClientProfileでは出ません。
今回はつぶやいた内容のTextと投稿ユーザ情報のscreen_nameを利用します。
つぶやきを表すStatusクラスとユーザ情報を表すUserクラスを以下のように作ります。
using System.Runtime.Serialization; namespace WTwitter.Model.Twitter { /// <summary> /// TwitterのJson形式データ /// </summary> [DataContract] class Status { [DataMember(Name = "text")] public string Text { set; get; } [DataMember(Name="user")] public User User { set; get; } public override string ToString() { return User.ScreenName + ":" + Text; } } }
using System.Runtime.Serialization; namespace WTwitter.Model.Twitter { /// <summary> /// TwitterのJson形式のユーザ情報 /// </summary> [DataContract] class User { [DataMember(Name = "screen_name")] public string ScreenName { get; set; } } }
StatusクラスがUser情報を持っていると言うことが表現できていると思います。
この情報を使って表示するようにWindow1クラスのWindow_Loadedメソッドを書き直します。
private void Window_Loaded(object sender, RoutedEventArgs e) { //取得するURL string url = "http://twitter.com/statuses/user_timeline/yuki1090.json"; //HTTP用の要求と応答 HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; HttpWebResponse response = request.GetResponse() as HttpWebResponse; //Json形式でデータを取得する DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List)); var stream = response.GetResponseStream(); var result = serializer.ReadObject(stream) as List; response.Close(); //取得した結果を1つ1行でTextboxに表示 foreach (var item in result) { ContentTextBox.AppendText(item.ToString() + Environment.NewLine); } }
今回のソースコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/37634
ソースだけでわかった人は以下読まなくてもOKです。
■解説
・プログラムのデータをファイルやネットのデータとして送受信するには
データを文字列に変換(シリアライズ)、文字からデータへ復元(デシリアライズ)します。
今回はJson形式で受信したテキストを分解ために
DataContractJsonSerializerを使います。
このクラスを使うと、変換を簡単にできます。
・シリアライザを使うときにはデータ形式を表すクラスに
[DataContract]
の属性を付けます。
またシリアライズ/デシリアライズの対象のクラス変数やプロパティに
[DataMember(Name = "???")]
を付けます。Name=???はJsonのどの部分に相当するかを表します。
・TwitterAPIの仕様のXMLのサンプルを見るとわかりますが、
1つのつぶやきはStatusという名前になっているので今回のクラス名もそうしました。
・Window1クラスの説明
-DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List
シリアライズ対象がStatusのリストであることを伝えて、インスタンス化します。
-var result = serializer.ReadObject(stream) as List
ストリームからシリアライザを利用してデータを読み込みます。
as List
変数resultに入れています。
-取得したresultには一連のStatusが入っていますので、
それぞれに対してToString()で文字列化してテキストボックスに追加していきます。
すいません。教えてください。
返信削除>foreach ステートメントは
>'System.Windows.Documents.List'が
>'GetEnumerator' のパブリック定義を
>含んでいないため、型
> 'System.Windows.Documents.List'
>の変数に対して使用できません。
って出てくるんですが、なにか根本的に間違っているような気がします。どうしたらいいんでしょう・・・。
すいません、教えてください。
返信削除ソースコードを見ていて分かったんですけど、
Status.cs
User.cs
ってどうやってファイルを作ったらいいんでしょうか?
今回のソースコード
返信削除http://wtwitter.codeplex.com/SourceControl/changeset/view/37634
は見てもらってますか?
どこかのUsingが足りないのかもしれません。
System.Windows.Documents.Listが予備されるのがおかしいので、
上記の不要なUsingがあって
System.Collections.Generic.List
に対するUsingが足りないのではないかと推測します。
ファイルの追加は、ソリューションエクスプローラで
返信削除右クリックして→追加→クラス
が早いかなと思います。
しのさんが指摘しているforeachのエラーは、Listの部分を適宜Listに変更することで解決しました。
返信削除「今回のソースコード」の方ではそのようになっているようですが、このページではそのようにはなっていないようです。
あと少し気になったのはSystem.ServiceModel.Webが参照の追加に出なかったことですね。
私はVisualStudio2010を使っているのですが、デフォルトでは.NET がClient Profileになっていたのでそこを変更する必要があるようです。
Status.csではset; get;の順になっているのに対して、
返信削除User.csではget; set;の順になっているのは何か理由があるのでしょうか?
setとgetの順番はまったく関係ないです。
返信削除動作には影響しません。
単に統一していないだけです。
Client Profileの件は本文に注釈をつけました。
ありがとうございました。
あ、訂正です
返信削除誤)Listの部分を適宜Listに変更することで解決しました。
正)Listの部分を適宜List<Status>に変更することで解決しました。
ありがとうございます。
返信削除<>で囲まれている部分は、blogに貼り付けるツールを通した段階で
消えちゃったのかもしれません。。