将json序列化为字典无法正常工作

时间:2017-05-19 14:38:05

标签: c# json json.net deserialization json-deserialization

我正在使用NewtonSoft的JsonConvert.DeserializeObject<AppraiserCalendarDto>(content)方法,并尝试反序列化以下内容,以确定某个资源是否在特定日期运行:

{
  "2017-05-18": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-19": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-22": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-23": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-24": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-25": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "2017-05-26": {
    "regular": {
      "recordType": "working",
      "workTimeStart": "08:00",
      "workTimeEnd": "22:00"
    }
  },
  "links": [
    {
      "rel": "canonical",
      "href": "https://api.somedomain.com/rest/core/v1/resources/workSchedules/calendarView?dateFrom=2017-05-18&dateTo=2017-05-28"
    },
    {
      "rel": "describedby",
      "href": "https://api.somedomain.com/rest/core/v1/metadata-catalog/resources"
    }
  ]
}

我要填充的模型类如下:

public class AppraiserCalendarDto
{
    public Dictionary<DateTime, Record> Records { get; set; }

    public class Record
    {
        [JsonProperty("recordType")]
        public string RecordType { get; set; }

        [JsonProperty("workTimeStart")]
        public TimeSpan WorkTimeStart { get; set; }

        [JsonProperty("workTimeEnd")]
        public TimeSpan WorkTimeEnd { get; set; }
    }

    public List<Link> Links { get; set; }

    public class Link
    {
        [JsonProperty("rel")]
        public string Rel { get; set; }

        [JsonProperty("href")]
        public string Href { get; set; }
    }
}

不幸的是,只有List<Link> Links被填充,Records字典为空。

我尝试使用Dictionary<string, Record>代替Dictionary<DateTime, Record>,结果相同。

非常感谢任何反馈。

2 个答案:

答案 0 :(得分:2)

这里有两个问题导致了这个问题。首先,您打算进入字典的时间条目在JSON中与links对象处于同一级别。反序列化器不会看到它们,因为它期望它们位于JSON中名为records的对象内,对应于AppraiserCalendarDto类中的字典属性的名称。第二个问题是每次进入记录都在JSON中名为regular的对象内,但模型中没有相应的类。

一种可能的解决方案是更改JSON以匹配您的模型,假设您可以控制JSON格式。但是,在我遇到的大多数问题中,这不是一个选项,因为JSON通常是提问者控制之外的第三方API。如果是这种情况,那么另一个选择是实现自定义JsonConverter来弥补差距。这是一个应该适合您的转换器:

class AppraiserCalendarDtoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(AppraiserCalendarDto));
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
                                    object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        var dto = new AppraiserCalendarDto();
        dto.Links = jo["links"].ToObject<List<AppraiserCalendarDto.Link>>();
        var dict = new Dictionary<DateTime, AppraiserCalendarDto.Record>();
        dto.Records = dict;
        foreach (JProperty prop in jo.Properties().Where(p => p.Name != "links"))
        {
            var date = DateTime.Parse(prop.Name);
            var record = prop.Value["regular"].ToObject<AppraiserCalendarDto.Record>();
            dict.Add(date, record);
        }
        return dto;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, 
                                   object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,您可以使用AppraiserCalendarDto属性标记[JsonConverter]类,如下所示:

[JsonConverter(typeof(AppraiserCalendarDtoConverter))]
public class AppraiserCalendarDto
{
    ...
}

或者,您可以将实例传递给JsonConvert.DeserializeObject<T>,如下所示:

var dto = JsonConvert.DeserializeObject<AppraiserCalendarDto>(content,
          new AppraiserCalendarDtoConverter());

演示小提琴:https://dotnetfiddle.net/yyErtO

答案 1 :(得分:0)

我检查了你的JSON并且它很好;我认为问题在于JsonConvert.DeserializeObject没有将这些重复实体本能地放入字典的逻辑。所以这就是我所看到的。首先,我拿了你的JSON并使用VS编辑 - &gt;粘贴特殊 - &gt;粘贴为json类。我弄得一团糟,请看这里的generated file。假设Newtonsoft和VS遵循类似的JSON解释逻辑,似乎那些连续的记录实例被解释为一个唯一的实体而不是集合或数组。我认为您将不得不使用一些自定义逻辑将json解析为您的类。只需将其反序列化为动态对象,然后通过它进行处理。祝你好运!