13

C# で JSON を逆シリアル化しようとする際に、情報を入手するのが難しいことに気づきました。

Google カスタム検索の結果が JSON 形式で返されます。手順を確認し、逆シリアル化を試みる順序を確立したいだけです。これは正しいですか?

  1. JSON 形式に一致するクラスを作成する必要があります。スキーマファイルを作成するようなものです。
  2. JavaScriptSerializer()クラスと メソッドを使用してdeserialize、関連するビットを抽出します。

私が遭遇するだろうと思われる問題の 1 つは、返されるすべてのデータを必要とせず、html リンクのみを必要とすることです。どうすればそれを達成できますか?

アップデート

次の JSON スニペットと C# コードで質問を更新しました。文字列 'links' をコンソールに出力したいのですが、うまくいきません。クラスを間違って定義していると思いますか?

Google カスタム検索からの JSON

handleResponse({
 "kind": "customsearch#search",
 "url": {
  "type": "application/json",
  "template": "https://www.googleapis.com/customsearch/v1?q\u003d{searchTerms}&num\u003d{count?}&start\u003d{startIndex?}&hr\u003d{language?}&safe\u003d{safe?}&cx\u003d{cx?}&cref\u003d{cref?}&sort\u003d{sort?}&alt\u003djson"
 },
 "queries": {
  "nextPage": [
   {
    "title": "Google Custom Search - lectures",
    "totalResults": 9590000,
    "searchTerms": "lectures",
    "count": 1,
    "startIndex": 2,
    "inputEncoding": "utf8",
    "outputEncoding": "utf8",
    "cx": "017576662512468239146:omuauf_lfve"
   }
  ],
  "request": [
   {
    "title": "Google Custom Search - lectures",
    "totalResults": 9590000,
    "searchTerms": "lectures",
    "count": 1,
    "startIndex": 1,
    "inputEncoding": "utf8",
    "outputEncoding": "utf8",
    "cx": "017576662512468239146:omuauf_lfve"
   }
  ]
 },
 "context": {
  "title": "Curriculum",
  "facets": [
   [
    {
     "label": "lectures",
     "anchor": "Lectures"
    }
   ],
   [
    {
     "label": "assignments",
     "anchor": "Assignments"
    }
   ],
   [
    {
     "label": "reference",
     "anchor": "Reference"
    }
   ]
  ]
 },
 "items": [
  {
   "kind": "customsearch#result",
   "title": "EE364a: Lecture Videos",
   "htmlTitle": "EE364a: \u003cb\u003eLecture\u003c/b\u003e Videos",
   "link": "http://www.stanford.edu/class/ee364a/videos.html",
   "displayLink": "www.stanford.edu",
   "snippet": "Apr 7, 2010 ... Course materials. Lecture slides · Lecture videos (2008) · Review sessions.   Assignments. Homework · Reading. Exams. Final exam ...",
   "htmlSnippet": "Apr 7, 2010 \u003cb\u003e...\u003c/b\u003e Course materials. \u003cb\u003eLecture\u003c/b\u003e slides · \u003cb\u003eLecture\u003c/b\u003e videos (2008) · Review sessions. \u003cbr\u003e  Assignments. Homework · Reading. Exams. Final exam \u003cb\u003e...\u003c/b\u003e",
   "cacheid": "TxVqFzFZLOsJ"
  }
 ]
}
);

C# スニペット

public class GoogleSearchResults
{
    public string link { get; set; }

}

public class Program
{
    static void Main(string[] args)
    {
        //input search term
        Console.WriteLine("What is your search query?:");
        string searchTerm = Console.ReadLine();

        //concantenate the strings using + symbol to make it URL friendly for google
        string searchTermFormat = searchTerm.Replace(" ", "+");

        //create a new instance of Webclient and use DownloadString method from the Webclient class to extract download html
        WebClient client = new WebClient();
        string Json = client.DownloadString("https://www.googleapis.com/customsearch/v1?key=My Key&cx=My CX&q=" + searchTermFormat);

        //create a new instance of JavaScriptSerializer and deserialise the desired content
        JavaScriptSerializer js = new JavaScriptSerializer();
        GoogleSearchResults results = js.Deserialize<GoogleSearchResults>(Json);

        Console.WriteLine(results);
        //Console.WriteLine(htmlDoc);
        Console.ReadLine();
    }
}

ありがとう

4

3 に答える 3

12

私はあなたの #2 アプローチを使用します: JavaScriptSerializerで逆シリアル化します。

これは、Facebook からの応答を逆シリアル化するために行うことです。

// get the id for the uploaded photo
var jss = new JavaScriptSerializer();
var resource = jss.Deserialize<Facebook.Data.Resource>(responseText);

.... Facebook.Data.Resource は次のように定義されています。

namespace Facebook.Data
{
    public class Resource
    {
        public string id { get; set; }
    }
}

responseText私がデシリアライズているのは次のようになります。

{"id":"10150111918987952",
 "from":{"name":"Someone",
     "id":"782272221"},
 "name":"uploaded from Cropper. (at 12\/15\/2010 7:06:41 AM)",
 "picture":"http:\/\/photos-f.ak.fbcdn.net\/hphotos-ak-snc4\/hs817.snc4\/69790_101501113333332_782377951_7551951_8193638_s.jpg",
 ...

しかし、Resourceクラスで定義されているプロパティが 1 つしかないため、それのみを逆シリアル化ます。逆シリアル化するクラスのフィールドを定義します。

もちろん、継承を使用しても機能します。次のようにデータ クラスを定義できます。

namespace Facebook.Data
{
  public class Resource
  {
    public string id { get; set; }
  }

  public class Person : Resource
  {
    public string name { get; set; }
  }

}

...そして、Personオブジェクトを逆シリアル化できます。


編集

OK、更新された質問で提供したサンプル json を考えると、応答を保持するクラスを次のように記述します。

public class GoogleSearchItem
{
    public string kind { get; set; }
    public string title { get; set; }
    public string link { get; set; }
    public string displayLink { get; set; }
    // and so on... add more properties here if you want
    // to deserialize them
}

public class SourceUrl
{
    public string type { get; set; }
    public string template { get; set; }
}

public class GoogleSearchResults
{
    public string kind { get; set; }
    public SourceUrl url { get; set; }
    public GoogleSearchItem[] items { get; set; }
    // and so on... add more properties here if you want to
    // deserialize them
}

逆シリアル化する C# コードは次のとおりです。

    // create a new instance of JavaScriptSerializer
    JavaScriptSerializer s1 = new JavaScriptSerializer();

    // deserialise the received response 
    GoogleSearchResults results = s1.Deserialize<GoogleSearchResults>(json);

    Console.WriteLine(s1.Serialize(results));

いくつかのコメント:

  • 検索結果を保持するトップレベル クラスは、GoogleSearchResults と呼ばれます。
  • GoogleSearchResults クラスの最初のkindプロパティは で、json オブジェクトの最初の名前付きプロパティに対応します。そのjsonオブジェクトのトップレベルのプロパティの名前ではないためlink、動作しません。link「リンク」という名前の json の階層の下位にプロパティがありますが、JavaScriptSerializer はそれらの下位レベルのものを上位レベルに引き出しません。
  • GoogleSearchResults クラスの次のプロパティは、SourceUrl 型です。これはurl、json のプロパティが単純な文字列ではないためです。これは、それぞれが文字列値を持つ 2 つのプロパティを持つ json オブジェクトです。そのため、C# のクラスとしての SourceUrl は 2 つの文字列プロパティを取得し、それぞれに適切な名前を付けて、これらの名前付きプロパティの 1 つを逆シリアル化します。
  • GoogleSearchResults クラスの次のプロパティは「items」と呼ばれ、json からアイテム ディクショナリを逆シリアル化できます。名前が示すように、items は json 内の配列であり、その値を角括弧で囲みます。これは、複数のアイテムが存在する可能性があることを意味しますが、あなたの場合はアイテムが 1 つしかありません。したがって、C# のこのプロパティは配列 (またはコレクション) でなければなりません。json の結果の各アイテムは単純な文字列ではないため、SourceUrl で行ったように、アイテム オブジェクトを逆シリアル化するホルダー クラスを定義する必要がありますGoogleSearchItem。このクラスには、一連の単純な文字列プロパティがあります。C# クラスのプロパティは、json が必要とする場合、int 型またはその他の型にすることもできます。
  • 最後に、結果を出力するときに、 を呼び出すだけで、によって暗黙的に呼び出されConsole.WriteLine(result)たメソッドの結果が表示されます。これは単にタイプの名前を出力するだけです。この場合は「GoogleSearchResults」ですが、これはあなたが望むものではないと思います。オブジェクトの内容を確認するには、先ほど示したようにシリアル化する必要があります。その出力には、逆シリアル化したものの値のみが表示されます。私が提供したクラスを使用すると、結果の情報は元のものよりも少なくなります。これは、一部の json プロパティに対応する C# クラスのプロパティを提供しなかったため、それらは逆シリアル化されていないためです。ToString()Console.WriteLine
于 2010-12-23T23:59:00.260 に答える
4

JSON を作成してクエリを実行するには、Json.NETとそのLINQサポートを参照してください。素敵な LINQ クエリを作成することで、必要なものだけを取得できます (選択、グループ化、カウント、最小、最大など、好きなものを何でもかまいません)。

于 2010-12-23T18:03:02.977 に答える
0

http://msdn.microsoft.com/en-us/library/bb412170.aspx

http://msdn.microsoft.com/en-us/library/bb410770.aspx

JSON表現をC#アプリで型に変換した後、必要なプロパティを引き出します。変換する前に、JSON表現から1つのプロパティのみを抽出する方法はないと思います(確かではありませんが)。

于 2010-12-23T18:08:19.770 に答える