使用C#反序列化JSON

时间:2010-12-23 17:59:52

标签: c# json deserialization

在尝试在C#中反序列化JSON时,发现在获取信息方面存在一些困难。

我收到了以JSON格式返回的Google自定义搜索结果。我只是想检查一下我的步骤,并确定尝试反序列化它的顺序。这是对的吗?

  1. 我需要创建匹配的类 JSON格式。有点像 创建模式文件。
  2. 使用JavaScriptSerializer()类和 deserialize方法提取 相关位。
  3. 我认为我将遇到的一个问题是我不需要返回所有数据,只需要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#Snippet

    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 个答案:

答案 0 :(得分: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类中只定义了一个属性,所以我只反序列化那个。定义类中要反序列化的字段。

当然,它可以使用继承。您可以像这样定义数据类:

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

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

}

...然后您可以反序列化Person对象。


修改

好的,鉴于您在更新后的问题中提供的示例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的层次结构中有一些名为“link”的属性较低,但JavaScriptSerializer不会将这些较低级别的内容提取到更高级别。
  • 我的GoogleSearchResults类中的下一个属性是SourceUrl类型。这是因为json中的url属性不是一个简单的字符串 - 它是一个带有两个属性的json对象,每个属性都有一个字符串值。因此,作为C#中的类的SourceUrl获取两个字符串属性,每个属性都具有相应的名称以反序列化其中一个命名属性。
  • GoogleSearchResults类中的下一个属性称为“items”,以便它可以从json反序列化项目字典。现在,顾名思义,项目是json中的一个数组,由围绕其值的方括号表示。这意味着可以有多个项目,但在您的情况下只有一个项目。所以C#中的这个属性必须是一个数组(或集合)。 json结果中的每个项目都不是一个简单的字符串,因此,正如我们对SourceUrl所做的那样,我们需要定义一个holder类来反序列化item对象:GoogleSearchItem。这个类有一堆简单的字符串属性。 C#类中的属性也可以是int类型或其他类型,如果这是json所需要的。
  • 最后,在打印出结果时,如果您只是致电Console.WriteLine(result),您会看到ToString()隐式调用的Console.WriteLine方法的结果。这只会打印出类型的名称,在这种情况下是“GoogleSearchResults”,我认为这不是你想要的。为了查看对象中的内容,您需要对其进行序列化,如我所示。在输出中,您将只看到反序列化的值。使用我提供的类,结果的信息将少于原始类,因为我没有在C#类中提供与某些json属性相对应的属性,因此没有反序列化。

答案 1 :(得分:4)

您可以查看Json.NET及其LINQ支持来创建和查询JSON。通过制作一个漂亮的LINQ查询,您将只获得所需的东西(您可以选择,分组,计数,分钟,最大,无论您喜欢什么)。

答案 2 :(得分:0)

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

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

在将JSON表示转换为C#应用程序中的类型后,拉出所需的属性。我认为在转换它之前,有一种方法只能从JSON表示中提取一个属性(虽然我不确定)。