如何使用通用类型的命名属性建模 JSON
How to model JSON with named properties on a common type
这是示例 JSON:
{
"notifications": [
{
"Profile.Guestbook.Post": {
"TargetIntId": 1,
"Digest": true,
"DigestSchedule": "00 * * * * *"
},
"Profile.MediaEntry.Post": {
"TargetIntId": 1,
"Digest": true,
"DigestSchedule": "00 * * * * *"
}
}
]
}
我正在尝试序列化到 C# 类,其中 NotificationInfo
实例的 EventName
是键的值,event.namespace1
和 event2.namespaceX
public class Preferences
{
public List<NotificationInfo> Notifications { get;set; }
}
public class NotificationInfo
{
public string EventName { get;set; }
public int TargetIntId { get;set; }
public bool Digest { get;set; }
}
我创建了一个 dotnetfiddle:https://dotnetfiddle.net/8oqniT
使事情正常进行的最简单方法是将您的模型更改为以下内容:
public class Preferences
{
public List<Dictionary<string, NotificationInfo>> Notifications { get; set; }
}
public class NotificationInfo
{
public int TargetIntId { get; set; }
public bool Digest { get; set; }
}
JSON 中的事件名称将成为列表中字典的键。
Fiddle: https://dotnetfiddle.net/P3yD3p
但是,这个模型使用起来有点笨拙,正如您在 fiddle 中看到的那样。在我看来,更好的方法是保留原始模型并使用自定义 JsonConverter
来处理翻译。这是转换器所需的代码:
public class NotificationsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(List<NotificationInfo>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var array = JArray.Load(reader);
return array.Children<JObject>()
.SelectMany(jo => jo.Properties())
.Select(jp => new NotificationInfo
{
EventName = jp.Name,
TargetIntId = (int)jp.Value["TargetIntId"],
Digest = (bool)jp.Value["Digest"]
})
.ToList();
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用它,只需将 [JsonConverter]
属性添加到您的 Notifications
属性,如下所示:
[JsonConverter(typeof(NotificationsConverter))]
public List<NotificationInfo> Notifications { get; set; }
Fiddle: https://dotnetfiddle.net/vkjXC0
这是示例 JSON:
{
"notifications": [
{
"Profile.Guestbook.Post": {
"TargetIntId": 1,
"Digest": true,
"DigestSchedule": "00 * * * * *"
},
"Profile.MediaEntry.Post": {
"TargetIntId": 1,
"Digest": true,
"DigestSchedule": "00 * * * * *"
}
}
]
}
我正在尝试序列化到 C# 类,其中 NotificationInfo
实例的 EventName
是键的值,event.namespace1
和 event2.namespaceX
public class Preferences
{
public List<NotificationInfo> Notifications { get;set; }
}
public class NotificationInfo
{
public string EventName { get;set; }
public int TargetIntId { get;set; }
public bool Digest { get;set; }
}
我创建了一个 dotnetfiddle:https://dotnetfiddle.net/8oqniT
使事情正常进行的最简单方法是将您的模型更改为以下内容:
public class Preferences
{
public List<Dictionary<string, NotificationInfo>> Notifications { get; set; }
}
public class NotificationInfo
{
public int TargetIntId { get; set; }
public bool Digest { get; set; }
}
JSON 中的事件名称将成为列表中字典的键。
Fiddle: https://dotnetfiddle.net/P3yD3p
但是,这个模型使用起来有点笨拙,正如您在 fiddle 中看到的那样。在我看来,更好的方法是保留原始模型并使用自定义 JsonConverter
来处理翻译。这是转换器所需的代码:
public class NotificationsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(List<NotificationInfo>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var array = JArray.Load(reader);
return array.Children<JObject>()
.SelectMany(jo => jo.Properties())
.Select(jp => new NotificationInfo
{
EventName = jp.Name,
TargetIntId = (int)jp.Value["TargetIntId"],
Digest = (bool)jp.Value["Digest"]
})
.ToList();
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用它,只需将 [JsonConverter]
属性添加到您的 Notifications
属性,如下所示:
[JsonConverter(typeof(NotificationsConverter))]
public List<NotificationInfo> Notifications { get; set; }
Fiddle: https://dotnetfiddle.net/vkjXC0