首页 > 解决方案 > 反序列化 JSON 数组与列表

问题描述

所以我正在使用这个 myMarketNews api:https ://mymarketnews.ams.usda.gov/mars-api/getting-started

我可以使用以下代码自己提取报告列表:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Authenticators;

namespace MarketNewsJson
{
    internal static class MarketNewsJson
    {
        private static void Main(string[] args)
        {
            var client = new RestClient("https://marsapi.ams.usda.gov")
            {
                Authenticator = new HttpBasicAuthenticator("mars_test_343343", "")
            };

            var request = new RestRequest("services/v1.1/reports", DataFormat.Json);
            var response = client.Get(request);

            var reports = JsonConvert.DeserializeObject<List<Report>>(response.Content);
            foreach (var report in reports)
            {
                Console.WriteLine($"{report.SlugId} {report.SlugName} - {report.ReportTitle}");
            }
        }
    }

    public class Report
    {
        [JsonProperty("slug_id")]
        public string SlugId { get; set; }

        [JsonProperty("slug_name")]
        public string SlugName { get; set; }

        [JsonProperty("report_title")]
        public string ReportTitle { get; set; }

        [JsonProperty("published_date")]
        public string PublishedDate { get; set; }

        [JsonProperty("markets")]
        public List<string> Markets { get; set; }

        [JsonProperty("market_types")]
        public List<string> MarketTypes { get; set; }

        [JsonProperty("offices")]
        public List<string> Offices { get; set; }

        [JsonProperty("sectionNames")]
        public List<string> SectionNames { get; set; }
    }
}

这将提取报告名称及其其他属性。但是,我也希望能够自己提取单个报告的 JSON 信息。我注意到在“排序”选项卡中,它显示了单个报告的属性,并且对于指定单个报告,它类似于 var request = new RestRequest("services/v1.1/reports/1095", DataFormat.Json ); 报告 1095 本身,而不是所有报告的 /reports。当我这样做时,我收到反序列化错误:

Newtonsoft.Json.JsonSerializationException:'无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型 'System.Collections.Generic.List`1[MarketNewsJson.Report]',因为该类型需要 JSON 数组(例如 [1,2,3])正确反序列化。

这是因为单个报告的 JSON 格式与报告列表本身的格式不同吗?如果是这样,我是否需要一个新行来为单个报告反序列化它,而当我想获取单个报告及其属性时,只需将另一行注释掉?

编辑:JSON响应

这就是我当前仅提取报告名称、ID 和标题(工作正常)的 JSON 响应的样子:

[
   {
      "slug_id": "1034",
      "slug_name": "MD_DA105",
      "report_title": "Whey - Western & Eastern Europe Report",
      "published_date": "07/30/2020 08:25:01",
      "markets": ["N/A"],
       "market_types": ["Point of Sale"],
       "offices": ["Madison"],
       "sectionNames": []
    }, {
         "slug_id": "1035",
         "slug_name": "MD_DA106",
         "report_title": "Skim Milk Powder - Europe",
         "published_date": "07/30/2020 08:25:01",
          "markets": ["N/A"],
          "market_types": ["Point of Sale"],
          "offices": ["Madison"],
          "sectionNames": []
  }
]

从文档中可以看出,报告的各个数据应该是这样的:

{
  "results": [
    {
      "report_begin_date": "2018-01-08",
      "report_end_date": "2018-01-08",
      "published_date": "2018-01-31",
      "office_name": "Madison",
      "office_code": "DA-MD",
      "office_city": "Madison",
      "office_state": "WI",
      "market_location_name": "National Cold Storage",
      "market_location_city": "",
      "market_location_state": "WI",
      "group": null,
      "category": "Hard Products",
      "commodity": "Cheese",
      "market_type": "Cold Storage",
      "market_type_category": "Dairy Market",
      "slug_id": "1095",
      "slug_name": "MD_DA953",
      "community": "Dairy",
      "quality": "N/A",
      "holdings_unit": "LBS",
      "holdings_current_lbs": "96009227",
      "holdings_1stDayMTH_lbs": "96245049",
      "holdings_change_lbs": "-235822",
      "holdings_change_percent": "0.0000",
      "currentMTH_1stDay": "2018-01-01",
      "report_narrative": null,
      "commodity_narrative": null,
      "special_announcement": null
}

标签: c#json

解决方案


您将不得不使用两个不同的课程。一个用于列表,另一个用于 ReportObject。

对于services/v1.1/reports,您将需要使用帖子中已有的课程。但是对于您获得的报告services/v1.1/reports/1095,您将需要使用不同的类来反序列化您的响应。这主要是因为您得到的响应与没有 ID 时得到的报告大多不同。

public class ReportResultResponse {
    // This is a List of objects even though it might always be a single element in the json
    [JsonProperty("results")]
    public List<ReportResultForID> Results {get;set;}
}

public class ReportResultForID {
    [JsonProperty("report_begin_date")]
    public DateTime ReportBeginDate {get;set;}
    
    [JsonProperty("report_end_date")]
    public DateTime ReportEndDate {get;set;}
    ...

    [JsonProperty("slug_name")]
    public string SlugName {get;set;}
    ...
}

// Then for the reports you get with ID, you would deserialize like this,
var request = new RestRequest("services/v1.1/reports/1095", DataFormat.Json);
var response = client.Get(request);
var reports = JsonConvert.DeserializeObject<ReportResultResponse>(response.Content);


推荐阅读