无法使用嵌套数组反序列化JSON字符串

时间:2017-06-14 19:50:53

标签: c# json.net

我无法反序列化从Web源检索到的JSON字符串。我收到一条错误说明以下内容:

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"} ) into type 'NewsApp.ComplexTypes.NYTimes.Keyword' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

这也适用于名为Byline的属性。以下是生成的json2csharp模型:

public class Headline
{
    public string main { get; set; }
    public string kicker { get; set; }
}

public class Keywords
{
    public string rank { get; set; }
    public string name { get; set; }
    public string value { get; set; }
}

public class Byline
{
    public string organization { get; set; }
    public string original { get; set; }
    public List<string> person { get; set; }
}

public class Multimedia
{
    public string url { get; set; }
    public string format { get; set; }
    public int height { get; set; }
    public int width { get; set; }
    public string type { get; set; }
    public string subtype { get; set; }
    public string caption { get; set; }
    public string copyright { get; set; }
}

public class Doc
{
    public string web_url { get; set; }
    public string snippet { get; set; }
    public string lead_paragraph { get; set; }
    public string @abstract { get; set; }
    public string print_page { get; set; }
    public List<string> blog { get; set; }
    public string source { get; set; }
    public Headline headline { get; set; }
    public Keywords keywords { get; set; }
    public string pub_date { get; set; }
    public string document_type { get; set; }
    public string news_desK { get; set; }
    public string section_name { get; set; }
    public string subsection_name { get; set; }
    public Byline byline { get; set; }
    public string type_of_material { get; set; }
    public string _id { get; set; }
    public string word_count { get; set; }
    public string slideshow_credits { get; set; }
    public List<Multimedia> multimedia { get; set; }
}

public class Meta
{
    public int hits { get; set; }
    public int time { get; set; }
    public int offset { get; set; }
}

public class Response
{
    public List<Doc> docs { get; set; }
    public Meta meta { get; set; }
}

public class RootObject
{
    public Response response { get; set; }
}

这是从API调用返回的JSON的结构。

{
  "response": {
    "docs": [
      {
        "web_url": "string",
        "snippet": "string",
        "lead_paragraph": "string",
        "abstract": "string",
        "print_page": "string",
        "blog": [
          ""
        ],
        "source": "string",
        "headline": {
          "main": "string",
          "kicker": "string"
        },
        "keywords": {
          "rank": "string",
          "name": "string",
          "value": "string"
        },
        "pub_date": "string",
        "document_type": "string",
        "news_desK": "string",
        "section_name": "string",
        "subsection_name": "string",
        "byline": {
          "organization": "string",
          "original": "string",
          "person": [
            ""
          ]
        },
        "type_of_material": "string",
        "_id": "string",
        "word_count": "string",
        "slideshow_credits": "string",
        "multimedia": [
          {
            "url": "string",
            "format": "string",
            "height": 0,
            "width": 0,
            "type": "string",
            "subtype": "string",
            "caption": "string",
            "copyright": "string"
          }
        ]
      }
    ],
    "meta": {
      "hits": 0,
      "time": 0,
      "offset": 0
    }
  }
}

以下是我如何定义RootObject和Doc类

public class RootObject
{
    public Response response { get; set; }
}

public class Doc
{
    public Doc()
    {
        blog = new List<string>();
        headline = new NYTimes.Headline();
        keywords = new List<Keyword>();
        multimedia = new List<Multimedia>();
        byline = new Byline();
    }
    public string web_url { get; set; }
    public string snippet { get; set; }
    public string lead_paragraph { get; set; }
    public string @abstract { get; set; }
    public string print_page { get; set; }
    public List<string> blog { get; set; }
    public string source { get; set; }
    public Headline headline { get; set; }
    public List<Keyword> keywords { get; set; }
    public string pub_date { get; set; }
    public string document_type { get; set; }
    public string news_desK { get; set; }
    public string section_name { get; set; }
    public string subsection_name { get; set; }
    public Byline byline { get; set; }
    public string type_of_material { get; set; }
    public string _id { get; set; }
    public string word_count { get; set; }
    public string slideshow_credits { get; set; }
    public List<Multimedia> multimedia { get; set; }
}

这是一个小样本数据集。

{
    "copyright": "Copyright (c) 2013 The New York Times Company.  All Rights Reserved.",
    "response": {
        "meta": {
            "hits": 7644
        },
        "docs": [{
                "web_url": "https://www.nytimes.com/slideshow/2016/01/01/nytnow/the-week-on-instagram.html",
                "snippet": "Photos posted on @nytimes during the last week of 2015 took followers from an island in Antarctica to Times Square, before the ball dropped....",
                "lead_paragraph": "Photos posted on @nytimes during the last week of 2015 took followers from an island in Antarctica to Times Square, before the ball dropped.",
                "abstract": null,
                "print_page": null,
                "blog": [],
                "source": "The New York Times",
                "multimedia": [{
                        "width": 190,
                        "url": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-thumbWide.jpg",
                        "height": 126,
                        "subtype": "wide",
                        "legacy": {
                            "wide": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-thumbWide.jpg",
                            "wideheight": "126",
                            "widewidth": "190"
                        },
                        "type": "image"
                    },
                    {
                        "width": 600,
                        "url": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-articleLarge.jpg",
                        "height": 600,
                        "subtype": "xlarge",
                        "legacy": {
                            "xlargewidth": "600",
                            "xlarge": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-articleLarge.jpg",
                            "xlargeheight": "600"
                        },
                        "type": "image"
                    },
                    {
                        "width": 75,
                        "url": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-thumbStandard.jpg",
                        "height": 75,
                        "subtype": "thumbnail",
                        "legacy": {
                            "thumbnailheight": "75",
                            "thumbnail": "images/2016/01/01/nytnow/the-week-on-instagram-slide-8Y3Z/the-week-on-instagram-slide-8Y3Z-thumbStandard.jpg",
                            "thumbnailwidth": "75"
                        },
                        "type": "image"
                    }
                ],
                "headline": {
                    "main": "The Week on Instagram"
                },
                "keywords": [],
                "pub_date": "2016-01-01T00:00:00Z",
                "document_type": "multimedia",
                "news_desk": "NYT Now",
                "section_name": "NYT Now",
                "subsection_name": null,
                "byline": [],
                "type_of_material": "Slideshow",
                "_id": "5687cefb38f0d82225327003",
                "word_count": "24",
                "slideshow_credits": "Ben C. Solomon/The New York Times"
            },
            {
                "web_url": "https://wordplay.blogs.nytimes.com/2016/01/01/mass-master/",
                "snippet": "David Phillips provides our first Saturday challenge of 2016....",
                "lead_paragraph": null,
                "abstract": "David Phillips provides our first Saturday challenge of 2016.",
                "print_page": null,
                "blog": [],
                "source": "The New York Times",
                "multimedia": [{
                        "width": 190,
                        "url": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-thumbWide.jpg",
                        "height": 126,
                        "subtype": "wide",
                        "legacy": {
                            "wide": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-thumbWide.jpg",
                            "wideheight": "126",
                            "widewidth": "190"
                        },
                        "type": "image"
                    },
                    {
                        "width": 600,
                        "url": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-articleLarge.jpg",
                        "height": 400,
                        "subtype": "xlarge",
                        "legacy": {
                            "xlargewidth": "600",
                            "xlarge": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-articleLarge.jpg",
                            "xlargeheight": "400"
                        },
                        "type": "image"
                    },
                    {
                        "width": 75,
                        "url": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-thumbStandard.jpg",
                        "height": 75,
                        "subtype": "thumbnail",
                        "legacy": {
                            "thumbnailheight": "75",
                            "thumbnail": "images/2016/01/01/crosswords/0101yalejpg/0101yalejpg-thumbStandard.jpg",
                            "thumbnailwidth": "75"
                        },
                        "type": "image"
                    }
                ],
                "headline": {
                    "main": "Mass Master",
                    "kicker": "Wordplay"
                },
                "keywords": [{
                    "rank": "1",
                    "name": "subject",
                    "value": "Crossword Puzzles"
                }],
                "pub_date": "2016-01-01T22:00:56Z",
                "document_type": "blogpost",
                "news_desk": "Business",
                "section_name": "Crosswords & Games",
                "subsection_name": null,
                "byline": {
                    "person": [{
                        "organization": "",
                        "role": "reported",
                        "firstname": "Deb",
                        "rank": 1,
                        "lastname": "AMLEN"
                    }],
                    "original": "By DEB AMLEN"
                },
                "type_of_material": "Blog",
                "_id": "56873d8d38f0d82225326f90",
                "word_count": "618",
                "slideshow_credits": null
            },
            {
                "web_url": "https://krugman.blogs.nytimes.com/2016/01/01/friday-night-music-more-wild-reeds/",
                "snippet": "Harmony to soothe the soul....",
                "lead_paragraph": null,
                "abstract": "Harmony to soothe the soul.",
                "print_page": null,
                "blog": [],
                "source": "The New York Times",
                "multimedia": [],
                "headline": {
                    "main": "Friday Night Music: More Wild Reeds",
                    "kicker": "Paul Krugman"
                },
                "keywords": [],
                "pub_date": "2016-01-01T21:17:09Z",
                "document_type": "blogpost",
                "news_desk": "OpEd",
                "section_name": "Opinion",
                "subsection_name": null,
                "byline": {
                    "person": [{
                        "organization": "",
                        "role": "reported",
                        "firstname": "Paul",
                        "rank": 1,
                        "lastname": "KRUGMAN"
                    }],
                    "original": "By PAUL KRUGMAN"
                },
                "type_of_material": "Blog",
                "_id": "5687337938f0d82225326f8b",
                "word_count": "13",
                "slideshow_credits": null
            }
        ]
    }
}

我试图使用[JsonArray(AllowNullItems = true)]属性来装饰有问题的类,但无济于事。唯一没有例外的是当我将显式声明为类对象的变量更改为object时,但这并不完全理想。

非常感谢任何帮助。我似乎无法让这种反序列化工作。

对json进行反序列化的调用。

public void GetThisMonthsArticles()
{
    string endpoint = string.Format(Endpoint, new object[] { DateTime.Now.Year, DateTime.Now.Month, Resources.APIKeys.NYTimesAPI });
    HttpClient client = HttpPersistentClient.GetHttpClient(endpoint);

    WebClient wc = new WebClient();
    string json = wc.DownloadString(endpoint);

    RootObject = JsonConvert.DeserializeObject<RootObject>(json);
}

1 个答案:

答案 0 :(得分:0)

也许你在班上犯了一些错误。

您可以尝试使用此工具:https://jsonutils.com/

它将为您生成所有课程。请记住在下拉列表中选择JsonProperty。

然后你可以使用:

var object = JsonConvert.DeserializeObject<RootObject>(json);

最后,您可以通过对象的LINQ查询访问您的数据,以获得您所需的数据。 我希望它对你有用。