今回から少し簡潔に書いていきたいと思います。
わからないところは適宜検索したり、参考書などを見たり、質問したりしてください。
第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に貼り付けるツールを通した段階で
消えちゃったのかもしれません。。