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.

Excepción al intentar deserializar un objeto con la propiedad HttpResponseHeaders.

Estoy intentando serializar/deserializar un objeto de una clase que tiene una propiedad de tipo System.Net.Http.Headers.HttpResponseHeaders, pero estoy obteniendo una excepción como esta:

“Newtonsoft.Json.JsonSerializationException: ‘No se puede crear y
poblar el tipo de lista System.Net.Http.Headers.HttpResponseHeaders.
Ruta ‘httpResponseHeaders’, línea 1, posición 31.'”

Mi código es así:

 //Clase de plantilla con propiedades para serializar/deserializar
 public class Response
 {
     public int Id { get; set; }

     public HttpResponseHeaders httpResponseHeaders { get; set; }
 }

 //Método para crear un objeto de tipo HttpResponseHeaders
 static HttpResponseHeaders CreateHttpResponseHeaders()
 {
     var myType = typeof(HttpResponseHeaders);
     var types = Array.Empty<type>();
     var constructorInfoObject =
         myType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, types, null);

     return (HttpResponseHeaders)constructorInfoObject.Invoke(null);
 }

 //Prueba de serialización/deserialización
 var response = new Response();
 response.Id = 1;

 response.httpResponseHeaders = CreateHttpResponseHeaders();
 response.httpResponseHeaders.WwwAuthenticate.Add(new AuthenticationHeaderValue("Negotiate"));

 var responseSerialized = JsonConvert.SerializeObject(response);
 var responseDeserialized = JsonConvert.DeserializeObject<response>(responseSerialized);

La clase HttpResponseHeaders está sellada y no tiene un constructor. La versión es Assembly System.Net.Http, Version=4.2.2.0.

Puedo serializar exitosamente, pero al deserializar aparece la excepción descrita anteriormente. ¿Alguien tiene una idea de cómo solucionarlo?

¡Gracias!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que la clase HttpResponseHeaders no puede ser deserializada por la biblioteca Newtonsoft.Json porque no tiene un constructor público sin parámetros. Una posible solución alternativa es crear un JsonConverter personalizado que sepa cómo serializar y deserializar objetos HttpResponseHeaders. Esto es lo que puedes hacer:

    1. Define una clase convertidora personalizada:
    public class HttpResponseHeadersConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) =>
            objectType == typeof(HttpResponseHeaders);
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var headers = (HttpResponseHeaders)existingValue ?? new HttpResponseHeaders();
            var token = JToken.Load(reader);
    
            foreach (var child in token.Children<jproperty>())
            {
                var headerName = child.Name;
                var headerValues = child.Value.Values<string>();
    
                headers.TryAddWithoutValidation(headerName, headerValues);
            }
    
            return headers;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var headers = (HttpResponseHeaders)value;
    
            writer.WriteStartObject();
    
            foreach (var header in headers)
            {
                writer.WritePropertyName(header.Key);
                serializer.Serialize(writer, header.Value);
            }
    
            writer.WriteEndObject();
        }
    }
    

    Este convertidor se encargará de la serialización y deserialización JSON de los objetos HttpResponseHeaders.

    1. Marca la propiedad httpResponseHeaders con el atributo JsonConverter:
    public class Response
    {
        public int Id { get; set; }
    
        [JsonConverter(typeof(HttpResponseHeadersConverter))]
        public HttpResponseHeaders httpResponseHeaders { get; set; }
    }
    

    Esto le indica a la biblioteca Newtonsoft.Json que utilice HttpResponseHeadersConverter para la serialización y deserialización de la propiedad httpResponseHeaders.

    1. Utiliza la propiedad JsonConvert.DefaultSettings para configurar el serializador:
    JsonConvert.DefaultSettings = () => new JsonSerializerSettings
    {
        Converters = { new HttpResponseHeadersConverter() },
        ContractResolver = new CamelCasePropertyNamesContractResolver()
    };
    

    Esto le indica a la biblioteca Newtonsoft.Json que utilice HttpResponseHeadersConverter para todas las propiedades HttpResponseHeaders y que utilice nombres de propiedades en formato camelCase en el JSON serializado.

    Con estos cambios, deberías poder serializar y deserializar objetos Response que contengan propiedades HttpResponseHeaders sin generar ninguna excepción.

Comments are closed.