Десериализация JSON с использованием C # - PullRequest
13 голосов
/ 23 декабря 2010

Обнаружение некоторых трудностей в поиске информации при попытке десериализации JSON в C #.

У меня есть результаты пользовательского поиска Google, возвращенные в формате JSON.Я просто хочу проверить мои шаги и установить порядок, пытаясь десериализовать его.Это правильно?

  1. Мне нужно создать классы, соответствующие формату JSON.Вроде как создание файла схемы.
  2. Используйте класс JavaScriptSerializer() и метод deserialize для извлечения соответствующих битов.

Одна из проблем, с которыми я столкнусь, заключается в том, что я нетребуются все возвращаемые данные, но только ссылки html.Как мне этого добиться?

ОБНОВЛЕНИЕ

Я обновил свой вопрос следующим фрагментом JSON и кодом C #.Я хочу вывести строку 'links' на консоль, но она не работает.Я думаю, что я неправильно определяю свои занятия?

JSON из пользовательского поиска Google

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

Спасибо

Ответы [ 3 ]

12 голосов
/ 24 декабря 2010

Я использую ваш # 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; }
    }
}

1011 *, который я десериализирую из , выглядит следующим образом:

{"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, я только десериализовал что .Определите поля в вашем классе, которые вы хотите десериализовать.

Конечно, работает наследование.Вы можете определить свои классы данных следующим образом:

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

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

}

... и затем вы можете десериализовать объект Person.


EDIT

Хорошо, учитывая пример 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.У вас есть link, который не будет работать, потому что link не является именем свойства верхнего уровня в этом объекте json.В иерархии вашего json есть свойства, называемые «ссылками», но JavaScriptSerializer не вытащит эти вещи более низкого уровня на более высокий уровень.
  • Следующее свойство в моем классе GoogleSearchResults имеет тип SourceUrl.Это связано с тем, что свойство url в json - это не простая строка - это объект json с двумя свойствами, каждое из которых имеет строковое значение.Поэтому SourceUrl как класс в C # получает два строковых свойства, каждое из которых имеет соответствующее имя для десериализации одного из названных свойств.
  • следующее свойство в классе GoogleSearchResults называется «items», чтобы оно могло десериализовать словарь элементов из вашего json.Теперь items, как следует из названия, представляет собой массив в json, обозначенный квадратной скобкой вокруг его значения.Это означает, что может быть более одного элемента, хотя в вашем случае есть только один элемент.Так что это свойство в C # должно быть массивом (или коллекцией).Каждый элемент в результате json не является простой строкой, поэтому, как и в случае с SourceUrl, нам нужно определить класс-держатель для десериализации объекта: GoogleSearchItem.Этот класс имеет множество простых строковых свойств.Свойства в классе C # также могут иметь тип int или какой-либо другой тип, если этого требует json.
  • наконец, при распечатке результата, если вы просто вызовете Console.WriteLine(result), вы увидите результат метода ToString(), который неявно вызывается Console.WriteLine.Это просто напечатает имя типа, в данном случае это «GoogleSearchResults», что, я думаю, не то, что вы хотите.Чтобы увидеть, что находится в объекте, вам нужно его сериализовать, как я показал.В результате этого вы увидите только значения вещей, которые вы десериализовали .Используя предоставленные мною классы, результат будет иметь меньше информации, чем исходный, потому что я не предоставил свойства в классе C #, соответствующие некоторым свойствам json, поэтому они не были десериализованы.
4 голосов
/ 23 декабря 2010

Вы можете взглянуть на Json.NET и его поддержку LINQ для создания и запроса JSON.Создавая симпатичный запрос LINQ, вы получите только то, что вам нужно (вы можете выбрать, сгруппировать по, количеству, минимуму, максимуму, что угодно).

0 голосов
/ 23 декабря 2010

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

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

Извлеките необходимое свойство после преобразования представления JSON в тип в приложении C #.Я не думаю, что есть способ извлечь только одно свойство из представления JSON до того, как вы его преобразовали (хотя я не уверен).

...