Tengo una clase que tiene un constructor predeterminado y también un constructor sobrecargado que toma un conjunto de parámetros. Estos parámetros coinciden con los campos del objeto y se asignan en la construcción. En este punto, necesito el constructor predeterminado para otros fines, por lo que me gustaría mantenerlo si puedo.
Mi problema: si elimino el constructor predeterminado y paso la cadena JSON, el objeto se deserializa correctamente y pasa los parámetros del constructor sin ningún problema. Termino recuperando el objeto poblado de la forma que esperaría. Sin embargo, tan pronto como agrego el constructor predeterminado en el objeto, cuando llamo a JsonConvert.DeserializeObject<Result>(jsontext)
las propiedades ya no se rellenan.
En este punto, he intentado agregar new JsonSerializerSettings(){CheckAdditionalContent = true}
a la llamada de deserialización. eso no hizo nada.
Otra nota. los parámetros del constructor coinciden exactamente con los nombres de los campos, excepto que los parámetros comienzan con una letra minúscula. No creo que esto importe ya que, como mencioné, la deserialización funciona bien sin un constructor predeterminado.
Aquí hay una muestra de mis constructores:
public Result() { }
public Result(int? code, string format, Dictionary<string, string> details = null)
{
Code = code ?? ERROR_CODE;
Format = format;
if (details == null)
Details = new Dictionary<string, string>();
else
Details = details;
}
Respuestas:
Json.Net prefiere usar el constructor predeterminado (sin parámetros) en un objeto si hay uno. Si hay varios constructores y desea que Json.Net use uno no predeterminado, puede agregar el
[JsonConstructor]
atributo al constructor al que desea que llame Json.Net.Es importante que los nombres de los parámetros del constructor coincidan con los nombres de propiedad correspondientes del objeto JSON (ignorando mayúsculas y minúsculas) para que esto funcione correctamente. Sin embargo, no necesariamente tiene que tener un parámetro constructor para cada propiedad del objeto. Para aquellas propiedades de objeto JSON que no están cubiertas por los parámetros del constructor, Json.Net intentará usar los accesos de propiedad pública (o propiedades / campos marcados con
[JsonProperty]
) para llenar el objeto después de construirlo.Si no desea agregar atributos a su clase o no controla el código fuente de la clase que está tratando de deserializar, otra alternativa es crear un JsonConverter personalizado para crear instancias y llenar su objeto. Por ejemplo:
Luego, agregue el convertidor a la configuración de su serializador y use la configuración cuando deserialice:
fuente
JsonConverter
para su clase. Esto eliminaría la dependencia, pero luego tendría que manejar la creación de instancias y llenar el objeto usted mismo en el convertidor. También podría ser posible escribir una costumbreContractResolver
que dirija a Json.Net a usar el otro constructor cambiando suJsonObjectContract
, pero esto podría resultar un poco más complicado de lo que parece.using Newtonsoft.Json;
Un poco tarde y no exactamente adecuado aquí, pero agregaré mi solución aquí, porque mi pregunta se había cerrado como un duplicado de esta, y porque esta solución es completamente diferente.
Necesitaba una forma general de instruir
Json.NET
para preferir el constructor más específico para un tipo de estructura definido por el usuario, por lo que puedo omitir losJsonConstructor
atributos que agregarían una dependencia al proyecto donde se define cada estructura.Realicé ingeniería inversa un poco e implementé un solucionador de contratos personalizado donde anulé el
CreateObjectContract
método para agregar mi lógica de creación personalizada.Lo estoy usando así.
fuente
objectType.IsValueType
) y esto funciona muy bien, ¡gracias!Basado en algunas de las respuestas aquí, he escrito un
CustomConstructorResolver
para usar en un proyecto actual, y pensé que podría ayudar a alguien más.Admite los siguientes mecanismos de resolución, todos configurables:
Newtonsoft.Json.JsonConstructorAttribute
.Aquí está la versión completa con documentación XML como un resumen: https://gist.github.com/maverickelementalch/80f77f4b6bdce3b434b0f7a1d06baa95
Comentarios apreciados.
fuente
El comportamiento predeterminado de Newtonsoft.Json va a encontrar los
public
constructores. Si el constructor por defecto sólo se utiliza en la contención de la clase o del mismo conjunto, se puede reducir el nivel de acceso aprotected
, ointernal
de manera que Newtonsoft.Json escogerá su deseadapublic
constructor.Es cierto que esta solución está bastante limitada a casos específicos.
fuente
Solución:
Modelo:
fuente