【问题标题】:Deserialize from json where can be single T object or array of T into List<T> [duplicate]从 json 反序列化,其中可以是单个 T 对象或 T 数组到 List<T> [重复]
【发布时间】:2014-10-24 04:44:36
【问题描述】:

我有这样的代码:

var json = GetJsonData(path);
JObject event_dates_data = JObject.Parse(json);
var event_dates_list = JObject.Parse(event_dates_data["document"]["date"].ToString());
var event_dates = JsonConvert.DeserializeObject<List<EventDate>>(event_dates_list.ToString());

Json 可能包含一个数组对象(例如“date:[{},{},{}]”)或只包含一个(例如“date:{}”)

Json 看起来像这样:

{
"document": {
"result": "success",
"resultcode": "000000",
"note": null,
"totaldates": "1",
"date": {
  "date_id": "351314",
  "live": "n",
  "datestart": "2012-03-07",
  "dateend": "2015-03-07",
  "timestart": "12:00",
  "timeend": "14:00",
  "date_available": "10000"
}
}
}

或者:

{
"document": {
"result": "success",
"resultcode": "000000",
"note": null,
"totaldates": "4",
"date": [
  {
    "date_id": "346022",
    "live": "n",
    "datestart": "2011-02-19",
    "dateend": "2011-02-19",
    "timestart": "12:00",
    "timeend": "14:00",
    "date_available": "10000"
  },
  {
    "date_id": "346023",
    "live": "n",
    "datestart": "2011-02-20",
    "dateend": "2011-02-20",
    "timestart": "12:00",
    "timeend": "14:00",
    "date_available": "10000"
  },
  {
    "date_id": "346024",
    "live": "n",
    "datestart": "2011-02-21",
    "dateend": "2011-02-21",
    "timestart": "12:00",
    "timeend": "14:00",
    "date_available": "10000"
  },
  {
    "date_id": "546580",
    "live": "y",
    "datestart": "2015-08-15",
    "dateend": "2015-08-15",
    "timestart": "12:00",
    "timeend": "14:00",
    "date_available": "10000"
  }
]
}
}

我有“日期”的 poco:

public class EventDate {

    [JsonProperty("date_id")]
    public string Id { get; set; }


    [JsonProperty("live")]
    [JsonConverter(typeof(AvailableForSalesFiledConverter))]
    public bool AvailableForSales { get; set; }


    [JsonProperty("datestart")]
    public string DateStart { get; set; }


    [JsonProperty("dateend")]
    public string DateEnd { get; set; }


    [JsonProperty("timestart")]
    public string TimeStart { get; set; }


    [JsonProperty("timeend")]
    public string TimeEnd { get; set; }


    [JsonProperty("date_available")]
    public int DateAvailable { get; set; }
}

所以当我尝试反序列化时,我得到了异常: "无法反序列化当前 JSON 对象(例如 {\"name\":\"value\"}) 进入类型'System.Collections.Generic.List`1 [TicketProvider.BrownPaperTickets.Entities.EventDate]' 因为该类型需要 JSON 数组(例如 [1,2,3])才能正确反序列化。\r\nTo 修复此错误或者将 JSON 更改为 JSON 数组(例如 [1,2,3]) 或更改反序列化类型,使其成为普通的 .NET 类型 (例如,不是像整数这样的原始类型,也不是像数组或列表这样的集合类型) 可以从 JSON 对象反序列化。 JsonObjectAttribute 也可以添加到 类型以强制它从 JSON 对象反序列化。\r\n路径 'date_id',第 2 行,第 13 位。" 我怎样才能把它列入清单?

【问题讨论】:

    标签: c# asp.net .net json.net


    【解决方案1】:
    var json = GetJsonData(path);
    JObject event_dates_data = JObject.Parse(json);
    var event_dates_list = JObject.Parse(event_dates_data["document"]["date"].ToString());
    event_dates_list = string.Format("[{0}]", event_dates_list.Trim('[', ']'));
    var event_dates = JsonConvert.DeserializeObject<List<EventDate>>(event_dates_list.ToString());
    

    【讨论】:

    • 当然.. 它有效。但我想应该有一些来自 Json.Net 库的标准方法。
    • 使用JsonConverter 是比手动操作和重新解析 JSON 更好的解决方案。请参阅链接的重复问题和答案。
    【解决方案2】:

    我有点困惑,因为你似乎在里面做混杂的事情。

    我建议您创建一个POCO 对象,将您的数据表示为一个类。它应该有一个DateTime 类型的列表和EventDate 类型之一,当你序列化时,你只需将整个类序列化为:

    var my_poco = // create your object here;
    var poco_as_json = Newtonsoft.Json.JsonConvert.SerializeObject(my_poco);
    
    // You then save that to a file (I assume that's what you're doing)
    
    // Get it back will look like: 
    var back_from_json = Newtonsoft.Json.JsonConvert
                                        .DeserializeObject<your_poco_class>(json);
    
    // and then simply use the object's lists:
    var dates  = back_from_json.event_dates_list; // list of dates
    var events = = back_from_json.events;         // list of events? 
    

    您的 poco 仅适用于活动日期。
    您需要另一个带有变量的 poco:

    “文档”、“结果”、“结果代码”、“注释”、“总日期”、“日期”

    它可能被称为documenttotaldates 将是一个 int,date 将是一个List&lt;DateEvent&gt;
    这就是您将序列化和反序列化的内容。

    【讨论】:

    • 感谢您的回答。我编辑了我的帖子,请再次查看。
    • downvoter ...原因?
    【解决方案3】:

    首先在你的类中将 RootObject 中类的实例转换为列表,例如:

    class RootObject
    {
    public List<Class1> Property1 { get; set; }
    }
    

    现在您可以以列表的形式访问该类中的项目。

    【讨论】:

    • 你错过了问题的重点——有时属性是一个数组,有时它是一个对象。如果将其声明为列表,则当 JSON 具有单个对象时它将不起作用,反之亦然。解决方案不仅仅是更改类声明(尽管这是其中的一部分)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2011-09-09
    • 2023-03-30
    相关资源
    最近更新 更多