c# - 使用 C# 反序列化 JSON

标签 c# json deserialization

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

我有以 JSON 格式返回的 Google 自定义搜索结果。我只想检查我的步骤并建立尝试反序列化的顺序。这样对吗?

  1. 我需要创建类来匹配 JSON 格式。有点像 创建架构文件。
  2. 使用 JavaScriptSerializer() 类和 deserialize 方法提取 相关位。

我认为我将要遇到的问题之一是我不需要返回所有数据,而只需要 html 链接。我怎样才能做到这一点?

更新

我已使用以下 JSON 片段和 C# 代码更新了我的问题。我想将字符串“链接”输出到控制台,但它似乎不起作用。我想我错误地定义了我的类(class)?

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

谢谢

最佳答案

我使用您的#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 对象中顶级属性的名称。在名为“link”的 json 层次结构中有较低的属性,但 JavaScriptSerializer 不会将那些较低级别的东西拉到较高级别。
  • 我的 GoogleSearchResults 类中的下一个属性是 SourceUrl 类型。这是因为 json 中的 url 属性不是一个简单的字符串——它是一个具有两个属性的 json 对象,每个属性都有一个字符串值。因此,作为 C# 中的一个类的 SourceUrl 获得两个字符串属性,每个属性都有适当的名称来反序列化其中一个命名属性。
  • GoogleSearchResults 类中的下一个属性称为“items”,因此它可以从您的 json 中反序列化 items 字典。顾名思义,Now items 是 json 中的一个数组,由其值周围的方括号表示。这意味着可以有多个项目,尽管在您的情况下只有一个项目。所以C#中的这个属性必须是数组(或集合)。 json 结果中的每个项目都不是一个简单的字符串,因此,再次,就像我们对 SourceUrl 所做的那样,我们需要定义一个 holder 类来反序列化项目对象:GoogleSearchItem。这个类有一堆简单的字符串属性。如果 json 需要,C# 类中的属性也可以是 int 类型或其他类型。
  • 最后,当打印出结果时,如果您只是调用 Console.WriteLine(result),您将看到隐式调用的 ToString() 方法的结果通过 Console.WriteLine。这只会打印类型的名称,在本例中是“GoogleSearchResults”,我认为这不是您想要的。为了查看对象中的内容,您需要将其序列化,如我所示。在其输出中,您只会看到您反序列化 的内容的值。使用我提供的类,结果将比原来的信息少,因为我没有在 C# 类中提供与某些 json 属性对应的属性,所以那些没有被反序列化。

关于c# - 使用 C# 反序列化 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4521239/

相关文章:

c# - EntityFramework 测试初始化​​错误 : CREATE DATABASE statement not allowed within multi-statement transaction

C# 泛型 - 为什么在以这种方式处理类型参数时需要显式转换?

javascript - React JS - 如何通过获取语句验证凭据

rust - 如何为实现特定特征的所有类型批量实现反序列化?

Ruby 反序列化 YAML

c# - 如何使用 openxml 和 C# 在 Excel 工作表中获取范围

c# - 结合 join 和 group by 时,EF Core 3.1 意外生成 SQL

php - 如何编写 PHP 脚本来获取给定用户在 Twitter 中的关注者数量?

python - 尝试使用 Python 通过 API 访问数据时出错

c# - WCF,如何实例化 DataContract 中的所有对象? [OnDeserializing] 不起作用