Entonces, por ejemplo, tengo varios tipos de autos que se serializan en un archivo .car (este es un proyecto escolar). Tengo tres tipos diferentes, Ford, Lexus y Dodge. Puedo salvarlos bien. Pero con la arquitectura actual de mi programa, cuando deserializo necesito saber el tipo antes de deserializar. Por ejemplo, estoy serializando así:

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

Cuando deserializo, necesito saber el tipo, antes de deserializar:

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

¿Cómo puedo conseguir esto? Gracias.

1
Connor 27 nov. 2021 a las 04:02
1
Tienes que publicar tu json si necesitas ayuda. Y tus clases también.
 – 
Serge
27 nov. 2021 a las 04:18

2 respuestas

La mejor respuesta

Si no conoce el tipo exacto de automóvil, su Json debe contener la propiedad que retenga su tipo

{
  "CarManufacturer" : "FORD"
}

Puede agregar esta propiedad manualmente a su clase

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; }
}

Y puede serializarlo de la siguiente manera

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

Deserializar

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

Esto debería resolver tu problema, pero tiene algunas desventajas.

  1. ¡Realizará la deserialización dos veces para el mismo objeto!
  2. Agregar alguna propiedad a sus modelos para que funcionen como discriminador de tipos
  3. Esta solución no funcionará si su clase base es una clase abstracta

Para superar este problema, debe escribir Convertidor personalizado Admite deserialización polimórfica esto agregará automáticamente el discriminador de tipos al json generado sin agregar ningún valor a su clase

3
Ibram Reda 27 nov. 2021 a las 06:48

¿Algo como esto?

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

Y entonces:

CurrentCar mycar = GetObjectDeserialized<CurrentCar.GetType()>(reader.ReadString());
-2
Leandro Bardelli 27 nov. 2021 a las 04:43
¿Eso es incluso compilar? El método GetType calculará el tipo en tiempo de ejecución, mientras que el parámetro genérico debe conocerse en tiempo de compilación ... además, no sé por qué envuelve una sola línea con el método
 – 
Ibram Reda
27 nov. 2021 a las 05:03
Eso no se compila. Y eso supone que el OP ya tiene una instancia del tipo que están tratando de deserializar.
 – 
Enigmativity
27 nov. 2021 a las 06:53
¿Por qué pusiste esto como respuesta? Los genéricos no se pueden resolver en tiempo de ejecución.
 – 
Andy
27 nov. 2021 a las 06:59