C# Как десериализовать Json в общий объект, использующий базовый класс?

Мне нужно преобразовать объект JSON в сущность, У меня много сущностей, и я не хочу писать свой код несколько раз, поэтому я создал базовый класс сущности и хочу выполнить десериализацию сущности (не зная, какая производная сущность вызывает базовую сущность).

Могу ли я это сделать?

Это мой базовый класс (это абстрактный класс)

  public abstract class AbstractEntity
{
    EntityState EntityState { get; set; }
    DateTime CreatedDate { get; set; }
    DateTime? ModifiedDate { get; set; }
    string CreatedBy { get; set; }
    string ModifiedBy { get; set; }

    public EntityState getEntityState()
    {
        return EntityState;
    }
    public void SetEntityState(EntityState entityState)
    {
        EntityState = entityState;
    }            
}

Первый энт:

public class TABLE1: AbstractEntity
{
    public TABLE1();

    public string ID{ get; set; }

    public string ADDRESS{ get; set; }
    public virtual ICollection<TABLE2> TABLE2 { get; set; }
}

Второй энт:

public class TABLE2: AbstractEntity
{
    public TABLE2();

    public string ID{ get; set; }

    public string ADDRESS{ get; set; }
    public virtual TABLE1 TABLE1{ get; set; }
}

Возможный дубликат Как преобразовать объект JSON в пользовательский объект C#?

CodeNotFound 10.06.2018 08:23

Пример в ссылке является универсальным преобразованием? Базовый класс не знает имя объекта

user1012506 10.06.2018 08:26

Как по JSON определить, какой тип сущности вам нужен (как человек, а не как компьютер)? Вы можете использовать JsonConverter

Llama 10.06.2018 08:29

@ user1012506 Если я правильно понял ваш вопрос, хотите ли вы десериализовать свой объект JSON в сущность или тип, которому не нужно знать базовый класс / тип, от которого нужно унаследовать?

Juniuz 10.06.2018 08:32

juniuz, да ты меня правильно понял ...

user1012506 10.06.2018 08:36

john, Мой вопрос не дублируется, потому что у меня больше 2-х сущностей .. Свойство is_album - неправильное использование generic

user1012506 10.06.2018 08:43

Итак, поскольку другой вопрос не является дословным дубликатом вашего, он недействителен? Это правда, что лошадь можно привести к воде, но нельзя заставить ее пить.

Llama 10.06.2018 09:21

Извините за то, что не принимаю, карта в ответе опирается на логическое свойство, чем не имеет отношения к более чем 2 объектам.

user1012506 10.06.2018 09:31

@ user1012506 - основная идея Десериализация полиморфных классов json без информации о типе с помощью json.net заключается в создании JsonConverter, который предварительно загружает JSON для каждого AbstractEntity в JToken, а затем выбирает соответствующий подтип, проверяя наличие и значения соответствующих свойств. См. Другие примеры в Массив Json для сопоставления настраиваемых объектов в C# и JsonConverter с интерфейсом.

dbc 10.06.2018 09:37

Хотя это правда, я уверен, что вы достаточно умны, чтобы экстраполировать, что вы могли бы использовать строку, например "type" и проверьте его значение, чтобы решить, какой тип C# вам нужен. Например: string type = item["type"].Value<string>();. Осознав это, я бы сказал, что дубликат полностью соответствует вашему вопросу.

Llama 10.06.2018 09:37

В вашем ответе я могу использовать только один раз в десериализации? вот что я хочу. не дублируется или десериализуется, я пишу инфраструктуры и не исправляю ошибки ...

user1012506 10.06.2018 09:41

@user Я добавил ответ в виде вики сообщества, чтобы помочь вам понять, как дубликат может применяться к вашей ситуации.

Llama 10.06.2018 10:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
13
2 528
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать JObject из библиотеки Newtonsoft.Json. Это сайт https://www.newtonsoft.com/json, на котором можно узнать, как его использовать. И много примеров кода также можно найти здесь https://www.newtonsoft.com/json/help/html/Samples.htm.

Например:

using Newtonsoft.Json.Serialization;

    public void Foo(string jsonData){
    var objData = (JObject)JsonConvert.DeserializeObject(jsonData); // Deserialize json data

    dynamic jObject = new JObject();
jObject.ID = objData.Value<string>("ID");
jObject.Address = objData.Value<string>("Address");
jObject.TABLE2 = objData.Value<JArray>("TABLE2");
    }

В приведенном выше примере кода jObject имеет динамический тип, который можно преобразовать в нужный вам тип.

Надеюсь это поможет.

Юний, спасибо! Значит, мне не нужно никаких изменений в базовом классе?

user1012506 10.06.2018 09:22

Не беспокойтесь @ user1012506, вам не нужно менять базовый класс, если вы этого хотите. Просто вы можете создать экземпляр объекта типа без фактического типа, используя ключевое слово dynamic. Вы можете обратиться к этому SO-ответу для получения более подробной информации о dynamicstackoverflow.com/questions/2690623/…

Juniuz 10.06.2018 09:33

Хорошо, я не могу написать универсальную десериализацию, вот ответ! (Я попросил десериализацию в базовом классе, чтобы не писать повторяющийся код)

user1012506 10.06.2018 09:37

@ user1012506, да, вы можете использовать тип T, который десериализует ваши данные json. Например: var fooBar = JsonConvert.DeserializeObject<dynamic>(jsonData);

Juniuz 10.06.2018 09:42
Ответ принят как подходящий

Связанный дубликат, вероятно, является лучшим универсальным решением:

public class AbstractEntityConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(AbstractEntity);
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        var type = item["TYPE"].Value<string>();
        switch (type)
        {
            case "TABLE1":
                return item.ToObject<TABLE1>();
            case "TABLE2":
                return item.ToObject<TABLE2>();
            default:
                return null;
        }
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Применение:

string json = "{\"TYPE\":\"TABLE1\",\"CreatedDate\":\"2018-06-10T08:00:00.000Z\",\"CreatedBy\":\"John\",\"ID\":\"1\",\"ADDRESS\":\"1 Road Street\",\"TABLE2\":[{\"CreatedDate\":\"2018-06-10T08:00:00.000Z\",\"CreatedBy\":\"John\",\"ID\":\"2\",\"ADDRESS\":\"2 Road Street\"}]}";
var settings = new JsonSerializerSettings()
{
    Converters = new List<JsonConverter>()
    {
        new AbstractEntityConverter()
    }
};
var obj = JsonConvert.DeserializeObject<AbstractEntity>(json, settings);

Конечно, вы можете определить свои JsonSettings в центральном месте, чтобы вам не приходилось писать объявление каждый раз, когда вы его используете.

P.S. Я решил использовать свойство «тип», поскольку вы не показали свой JSON или свой метод определения класса для десериализации. При необходимости замените его собственной логикой.

Попробуйте онлайн

Другие вопросы по теме