Pregunta

Encontrar una cierta dificultad en la obtención de información para tratar de deserializar JSON en C #.

Tengo los resultados de búsqueda personalizado de Google devuelve en formato JSON. Sólo quiero comprobar a través de mis pasos y establecer el orden en el que intenta deserializar ella. ¿Es esto así?

  1. Es necesario crear clases para que coincida el formato JSON. Algo así como una la creación de archivo de esquema.
  2. Utilice la clase y JavaScriptSerializer() método deserialize para extraer el bits relevantes.

Una de las cuestiones que creo que voy a correr en es que no necesito todos los datos devueltos, pero sólo los enlaces HTML. ¿Cómo puedo lograr eso?

Actualizar

He actualizado mi pregunta con el siguiente fragmento de JSON y código C #. Quiero salida de la cadena 'links' a la consola, pero no parece estar funcionando. Creo que estoy definiendo mis clases erróneamente?

JSON de Google Custom Search

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 # Fragmento

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();
    }
}

Gracias

¿Fue útil?

Solución

I use your #2 approach: deserialize with the JavaScriptSerializer.

This is what I do to deserialize a response from Facebook:

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

....where Facebook.Data.Resource is defined like this:

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

The responseText that I am deserializing from looks like this:

{"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",
 ...

But since I have only one property defined in the Resource class, I only deserialize that. Define the fields in your class that you want to deserialize.

It works to use inheritance, of course. You can define your data classes like this:

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

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

}

...and then you can deserialize a Person object.


EDIT

Ok, given the sample json you provided in the updated question, here's how I wrote the classes to hold the response:

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
}

And here's the C# code to deserialize:

    // 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));

Some comments:

  • The toplevel class to hold the search result is called GoogleSearchResults.
  • The first property in the GoogleSearchResults class is kind, corresponding to the first named property in the json object. You had link which isn't going to work, because link is not the name of a top-level property in that json object. There are properties lower in the hierarchy of your json named "link" but JavaScriptSerializer won't pull out those lower level things into the higher level.
  • The next property in my GoogleSearchResults class is of type SourceUrl. This is because the url property in the json is not a simple string - it is a json object with two properties, each with a string value. So SourceUrl as a class in C# gets two string properties, each with the appropriate name to deserialize one of those named properties.
  • the next property in the GoogleSearchResults class is called "items" so that it can deserialize the items dictionary from your json. Now items, as the name suggests, is an array in the json, as denoted by the square bracket around its value. This means there can be more than one item, although in your case there is just one item. So this property in C# must be an array (or collection). Each item in the json result is not a simple string, so, once again, as we did with SourceUrl, we need to define a holder class to deserialize the item object: GoogleSearchItem. This class has a bunch of simple string properties. The properties in the C# class could also be of type int or some other type, if that's what the json requires.
  • finally, when printing out the result, if you just call Console.WriteLine(result) you will see the result of the ToString() method that is implicitly invoked by Console.WriteLine. This will merely print the name of the type, in this case is "GoogleSearchResults", which is not what you want, I think. In order to see what's in the object, you need to serialize it, as I've shown. In the output of that, you will see only the values of things you deserialized. Using the classes I provided, the result will have less information than the original, because I didn't provide properties in the C# class corresponding to some of the json properties, so those weren't deserialized.

Otros consejos

You could take a look at Json.NET and its LINQ support to create and query JSON. By crafting a nice LINQ query you will get only the stuff you need (you can select, group by, count, min, max, whatever you like).

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

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

Pull out the property you need after you have converted the JSON representation to a type in your C# app. I don't think there's a way to extract only one property from the JSON representation before you have converted it (though I am not sure).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top