Как моделировать JSON с именованными свойствами на общем типе - PullRequest
0 голосов
/ 16 декабря 2018

Вот пример 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

1 Ответ

0 голосов
/ 17 декабря 2018

Самый простой способ заставить все работать - изменить вашу модель следующим образом:

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

Однако эта модель может быть немного неудобной в использовании, как вы можете видеть из скрипки.На мой взгляд, лучший подход - сохранить исходную модель и использовать пользовательский 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

...