【问题标题】:De-Serialize json to dictionary not working properly将 json 反序列化为字典无法正常工作
【发布时间】:2017-05-19 14:38:04
【问题描述】:

我正在使用 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&lt;Link&gt; Links 被填充,而Records 字典为空。

我尝试使用Dictionary&lt;string, Record&gt; 而不是Dictionary&lt;DateTime, Record&gt;,结果相同。

非常感谢任何反馈。

【问题讨论】:

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


    【解决方案1】:

    这里有两个问题导致了这个问题。首先,您打算进入字典的时间条目在 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();
        }
    }
    

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

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

    或者,您也可以像这样将实例传递给JsonConvert.DeserializeObject&lt;T&gt;

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

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

    【讨论】:

      【解决方案2】:

      我检查了你的 JSON,它很好;我认为问题在于 JsonConvert.DeserializeObject 没有将这些重复实体本质上放入字典的逻辑。这就是我所看到的。首先,我拿走了你的 JSON 并使用了 VS 编辑 -> 特殊粘贴 -> 粘贴为 json 类。我真的一团糟,请参阅此处的generated file。假设 Newtonsoft 和 VS 遵循类似的 JSON 解释逻辑,那么这些连续的记录实例似乎都被解释为一个唯一的实体,而不是一个集合或数组。我认为您将不得不使用一些自定义逻辑将 json 解析到您的类中。只需将其反序列化为动态对象并按照自己的方式进行操作。祝你好运!

      【讨论】:

        猜你喜欢
        • 2019-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-24
        • 2018-09-21
        • 2017-10-19
        • 2019-10-05
        相关资源
        最近更新 更多