如何使用通用类型的命名属性建模 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.namespace1event2.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