Так, например, у меня есть несколько типов автомобилей, которые сериализуются в файл .car (это школьный проект). У меня есть три разных типа: форд, лексус и додж. Я могу их спасти. Но с текущей архитектурой моей программы при десериализации мне нужно знать тип перед десериализацией. Например, я сериализую так:

if (CurrentCar.GetType() == typeof(Ford))
{
   var JSON_CAR = JsonSerializer.Serialize((Ford)CurrentCar);
   writer.Write(JSON_CAR);
}

Когда я выполняю десериализацию, мне нужно знать тип перед десериализацией:

CurrentCar = JsonSerializer.Deserialize<???>(reader.ReadString());

Как я могу этого добиться? Спасибо.

1
Connor 27 Ноя 2021 в 04:02
1
Вы должны опубликовать свой json, если вам нужна помощь. И твои занятия тоже.
 – 
Serge
27 Ноя 2021 в 04:18

2 ответа

Лучший ответ

Если вы не знаете точный тип автомобиля, ваш Json должен содержать свойство, содержащее его тип.

{
  "CarManufacturer" : "FORD"
}

Вы можете добавить это свойство вручную в свой класс

enum CarManufacturer
{
    FORD,
    BMW
}
class Car
{
    [JsonConverter(typeof(JsonStringEnumConverter))]
    public CarManufacturer Manufacturer { get; set; }
    public string Name { get; set; }
}

class Ford:Car
{
    public Ford()
    {
        Manufacturer = CarManufacturer.FORD;
    }
    public string OnlyFord { get; set; }
}

class BMW :Car
{
    public BMW()
    {
        Manufacturer = CarManufacturer.BMW; ;
    }
    public string OnlyBMW { get; set; }
}

И вы можете сериализовать его следующим образом

Car CurrentCar = new Ford { Name = "Foard Car", OnlyFord = "spacific feature in Ford Cars" };
string json = JsonSerializer.Serialize(CurrentCar, CurrentCar.GetType());
Console.WriteLine(json);

Десериализовать

Car Tempcar = JsonSerializer.Deserialize<Car>(json);
var Car = Tempcar.Manufacturer switch
{
    CarManufacturer.BMW => JsonSerializer.Deserialize<BMW>(json),
    CarManufacturer.FORD => JsonSerializer.Deserialize<Ford>(json),
    _ => Tempcar
};

Это должно решить вашу проблему, но имеет некоторые недостатки.

  1. Вы сделаете десериализацию два раза для одного и того же объекта!
  2. Добавление некоторых свойств к вашим моделям для работы в качестве дискриминатора типов
  3. Это решение не будет работать, если ваш базовый класс является абстрактным классом.

Чтобы решить эту проблему, вы должны написать Пользовательский преобразователь Поддержка полиморфной десериализации это автоматически добавит дискриминатор типов в сгенерированный json без добавления какого-либо значения в ваш класс

3
Ibram Reda 27 Ноя 2021 в 06:48

Что-то вроде этого?

public T GetObjectDeserialized<T>(string mydata) {
         return JsonSerializer.Serialize<T>(mydata);
}

А потом:

CurrentCar mycar = GetObjectDeserialized<CurrentCar.GetType()>(reader.ReadString());
-2
Leandro Bardelli 27 Ноя 2021 в 04:43
Это вообще компилировать ?! Метод GetType вычислит тип во время выполнения, в то время как параметр Generic должен быть известен во время компиляции .... более того, я не знаю, почему вы переносите одну строку с помощью метода
 – 
Ibram Reda
27 Ноя 2021 в 05:03
Это не компилируется. И это предполагает, что OP уже имеет экземпляр типа, который они пытаются десериализовать.
 – 
Enigmativity
27 Ноя 2021 в 06:53
Почему ты поставил это как ответ? Дженерики не могут разрешиться во время выполнения.
 – 
Andy
27 Ноя 2021 в 06:59