反序列化 json 到字典无法正常工作
De-Serialize json to dictionary not working properly
我正在使用 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"
}
]
}
我要填充的模型class如下:
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>
,结果相同。
非常感谢任何反馈。
这里有两个问题导致了这个问题。首先,您打算进入字典的时间条目在 JSON 中与 links
对象处于同一级别。反序列化器看不到它们,因为它希望它们位于 JSON 中名为 records
的对象内,对应于 AppraiserCalendarDto
中的字典名称 属性 class。第二个问题是每次条目记录都在 JSON 中名为 regular
的对象内,但在您的模型中没有对应的 class。
一个可能的解决方案是更改 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
class,如下所示:
[JsonConverter(typeof(AppraiserCalendarDtoConverter))]
public class AppraiserCalendarDto
{
...
}
或者,您也可以像这样将实例传递给 JsonConvert.DeserializeObject<T>
:
var dto = JsonConvert.DeserializeObject<AppraiserCalendarDto>(content,
new AppraiserCalendarDtoConverter());
演示 fiddle:https://dotnetfiddle.net/yyErtO
我检查了你的JSON,没问题;我认为问题是 JsonConvert.DeserializeObject 没有将这些重复实体本质上放入字典的逻辑。所以这就是我看过的。首先,我使用了你的 JSON 并使用了 VS 编辑 -> 特殊粘贴 -> 粘贴为 json 类。我弄得一团糟,请参阅此处的 generated file。假设 Newtonsoft 和 VS 遵循类似的 JSON 解释逻辑,看起来那些连续的记录实例被解释为每个唯一的实体而不是集合或数组。我认为您将不得不使用一些自定义逻辑将 json 解析为您的 类。只需将它反序列化为一个动态对象,然后按照自己的方式处理它。祝你好运!
我正在使用 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"
}
]
}
我要填充的模型class如下:
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>
,结果相同。
非常感谢任何反馈。
这里有两个问题导致了这个问题。首先,您打算进入字典的时间条目在 JSON 中与 links
对象处于同一级别。反序列化器看不到它们,因为它希望它们位于 JSON 中名为 records
的对象内,对应于 AppraiserCalendarDto
中的字典名称 属性 class。第二个问题是每次条目记录都在 JSON 中名为 regular
的对象内,但在您的模型中没有对应的 class。
一个可能的解决方案是更改 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
class,如下所示:
[JsonConverter(typeof(AppraiserCalendarDtoConverter))]
public class AppraiserCalendarDto
{
...
}
或者,您也可以像这样将实例传递给 JsonConvert.DeserializeObject<T>
:
var dto = JsonConvert.DeserializeObject<AppraiserCalendarDto>(content,
new AppraiserCalendarDtoConverter());
演示 fiddle:https://dotnetfiddle.net/yyErtO
我检查了你的JSON,没问题;我认为问题是 JsonConvert.DeserializeObject 没有将这些重复实体本质上放入字典的逻辑。所以这就是我看过的。首先,我使用了你的 JSON 并使用了 VS 编辑 -> 特殊粘贴 -> 粘贴为 json 类。我弄得一团糟,请参阅此处的 generated file。假设 Newtonsoft 和 VS 遵循类似的 JSON 解释逻辑,看起来那些连续的记录实例被解释为每个唯一的实体而不是集合或数组。我认为您将不得不使用一些自定义逻辑将 json 解析为您的 类。只需将它反序列化为一个动态对象,然后按照自己的方式处理它。祝你好运!