es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo deserializar JSON con el patrón de composición – C#, Json

Como tuve que buscar durante mucho tiempo una respuesta que funcionara tal como está, proporcionaré un ejemplo aquí, cuando se serializa y deserializa un objeto con una estructura de patrón compuesto.

Mi problema era deserializar este tipo de estructura de clase (https://en.wikipedia.org/wiki/Composite_pattern):

abstract class BaseClass
{
    public int Id { get; set; }
}

class Leaf : BaseClass
{
    public string Foo { get; set; }
}

class Composite : BaseClass
{
    public List<baseclass> ClassList = new List<baseclass>();
}

La serialización funcionó usando:

var composite = new Composite();
JsonConvert.SerializeObject(composite, Formatting.Indented);

La deserialización no funcionó de forma automática.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Después de buscar, encontré que para deserializar correctamente este tipo de estructura de clase, es necesario usar el atributo JsonConverter con un conversor personalizado que maneje los tipos polimórficos. Aquí tienes un ejemplo del conversor personalizado:

    public class BaseClassConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(BaseClass).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jo = JObject.Load(reader);
    
            if (jo["Foo"] != null) // Objeto hoja
            {
                var leaf = new Leaf();
                serializer.Populate(jo.CreateReader(), leaf);
                return leaf;
            }
            else if (jo["ClassList"] != null) // Objeto compuesto
            {
                var composite = new Composite();
                serializer.Populate(jo.CreateReader(), composite);
                return composite;
            }
    
            throw new InvalidOperationException("Tipo de objeto desconocido");
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    Para utilizar este conversor personalizado, necesitas aplicar el atributo JsonConverter a la clase abstracta BaseClass, de la siguiente manera:

    [JsonConverter(typeof(BaseClassConverter))]
    abstract class BaseClass { /* ... */ }
    

    Ahora, cuando deserialices un objeto JSON con esta estructura de clase, debería manejar correctamente los tipos polimórficos y crear los objetos correctos. Aquí tienes un ejemplo de deserialización:

    var json = "{\"Id\":1,\"ClassList\":[{\"Id\":2,\"Foo\":\"bar\"},{\"Id\":3}]}";
    var composite = JsonConvert.DeserializeObject<composite>(json);
    

    Esto debería crear correctamente un objeto Composite con dos elementos en ClassList, uno de tipo Leaf y otro de tipo BaseClass.

Comments are closed.