Soy relativamente nuevo en trabajar con datos de C # y JSON y estoy buscando orientación. Estoy usando C # 3.0, con .NET3.5SP1 y JSON.NET 3.5r6.
Tengo una clase de C # definida que necesito completar desde una estructura JSON. Sin embargo, no todas las estructuras JSON para una entrada que se recupera del servicio web contienen todos los atributos posibles que se definen dentro de la clase C #.
He estado haciendo lo que parece ser el camino incorrecto, difícil y simplemente seleccionando cada valor uno por uno del JObject y transformando la cadena en la propiedad de clase deseada.
JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);
MyAccount.EmployeeID = (string)o["employeeid"][0];
¿Cuál es la mejor manera de deserializar una estructura JSON en la clase C # y manejar los posibles datos faltantes de la fuente JSON?
Mi clase se define como:
public class MyAccount
{
[JsonProperty(PropertyName = "username")]
public string UserID { get; set; }
[JsonProperty(PropertyName = "givenname")]
public string GivenName { get; set; }
[JsonProperty(PropertyName = "sn")]
public string Surname { get; set; }
[JsonProperty(PropertyName = "passwordexpired")]
public DateTime PasswordExpire { get; set; }
[JsonProperty(PropertyName = "primaryaffiliation")]
public string PrimaryAffiliation { get; set; }
[JsonProperty(PropertyName = "affiliation")]
public string[] Affiliation { get; set; }
[JsonProperty(PropertyName = "affiliationstatus")]
public string AffiliationStatus { get; set; }
[JsonProperty(PropertyName = "affiliationmodifytimestamp")]
public DateTime AffiliationLastModified { get; set; }
[JsonProperty(PropertyName = "employeeid")]
public string EmployeeID { get; set; }
[JsonProperty(PropertyName = "accountstatus")]
public string AccountStatus { get; set; }
[JsonProperty(PropertyName = "accountstatusexpiration")]
public DateTime AccountStatusExpiration { get; set; }
[JsonProperty(PropertyName = "accountstatusexpmaxdate")]
public DateTime AccountStatusExpirationMaxDate { get; set; }
[JsonProperty(PropertyName = "accountstatusmodifytimestamp")]
public DateTime AccountStatusModified { get; set; }
[JsonProperty(PropertyName = "accountstatusexpnotice")]
public string AccountStatusExpNotice { get; set; }
[JsonProperty(PropertyName = "accountstatusmodifiedby")]
public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; }
[JsonProperty(PropertyName = "entrycreatedate")]
public DateTime EntryCreatedate { get; set; }
[JsonProperty(PropertyName = "entrydeactivationdate")]
public DateTime EntryDeactivationDate { get; set; }
}
Y una muestra del JSON para analizar es:
{
"givenname": [
"Robert"
],
"passwordexpired": "20091031041550Z",
"accountstatus": [
"active"
],
"accountstatusexpiration": [
"20100612000000Z"
],
"accountstatusexpmaxdate": [
"20110410000000Z"
],
"accountstatusmodifiedby": {
"20100214173242Z": "tdecker",
"20100304003242Z": "jsmith",
"20100324103242Z": "jsmith",
"20100325000005Z": "rjones",
"20100326210634Z": "jsmith",
"20100326211130Z": "jsmith"
},
"accountstatusmodifytimestamp": [
"20100312001213Z"
],
"affiliation": [
"Employee",
"Contractor",
"Staff"
],
"affiliationmodifytimestamp": [
"20100312001213Z"
],
"affiliationstatus": [
"detached"
],
"entrycreatedate": [
"20000922072747Z"
],
"username": [
"rjohnson"
],
"primaryaffiliation": [
"Staff"
],
"employeeid": [
"999777666"
],
"sn": [
"Johnson"
]
}
fuente
¿Has intentado usar el método genérico DeserializeObject?
Cualquier campo faltante en los datos JSON simplemente debe dejarse NULL.
ACTUALIZAR:
Si la cadena JSON es una matriz, intente esto:
jarray
entonces debería ser aList<MyAccount>
.OTRA ACTUALIZACIÓN:
La excepción que está obteniendo no es consistente con una variedad de objetos: creo que el serializador está teniendo problemas con su
accountstatusmodifiedby
propiedad de diccionario .Intente excluir la
accountstatusmodifiedby
propiedad de la serialización y vea si eso ayuda. Si lo hace, es posible que deba representar esa propiedad de manera diferente.Documentación: Serialización y deserialización de JSON con Json.NET
fuente
DateTime AccountStatusExpiration
(por ejemplo) no es anulable como se define en el código. ¿Qué se necesitaría para hacerlo anulable? Simplemente cambieDateTime
aDateTime?
?Puede usar el
dynamic
tipo C # para facilitar las cosas. Esta técnica también simplifica la refactorización, ya que no se basa en cadenas mágicas.Json
La
json
siguiente cadena es una respuesta simple de una llamada http api y define dos propiedades:Id
yName
.C#
Use
JsonConvert.DeserializeObject<dynamic>()
para deserializar esta cadena en un tipo dinámico y luego simplemente acceda a sus propiedades de la manera habitual.Nota : El enlace NuGet para el ensamblaje NewtonSoft es http://nuget.org/packages/newtonsoft.json . No olvides agregar:
using Newtonsoft.Json;
para acceder a esas clases.fuente
DeserializeObject<dynamic>
es, por definición, no "verificado por tipo". Por lo que las siguientes líneasresults.Id
yresults.Name
no se puede comprobar en tiempo de compilación. Cualquier error ocurrirá en tiempo de ejecución en su lugar. Compare esto con una llamada fuertemente tipada comoDeserializeObject<List<MyAccount>>
. Las referencias a esas propiedades se pueden confirmar en tiempo de compilación. El uso dedynamic
, aunque puede ser conveniente, introduce "cadenas mágicas" como nombres de propiedad; una reducción en la robustez en mi humilde opinión.Puedes usar:
aquí:
json
es la cadena json,obj
es el objeto de destino. Ver: ejemploNota:
PopulateObject()
no borrará los datos de la lista de obj, despuésPopulate()
, elobj's
miembro de la lista contendrá sus datos originales y los datos de la cadena jsonfuente
Partiendo de la respuesta de bbant, esta es mi solución completa para deserializar JSON desde una URL remota.
El uso sería como:
¿Dónde
FeedResult
se genera la clase con Xamasoft JSON Class Generator?Aquí hay una captura de pantalla de la configuración que utilicé, lo que permite nombres de propiedades extraños que la versión web no podía explicar.
fuente
Encontré que había construido mi objeto incorrectamente. Solía http://json2csharp.com/ a mí generar mi clase de objeto de la JSON. Una vez que obtuve el Oject correcto pude lanzar sin problemas. Norbit, error de Noob. Pensé en agregarlo en caso de que tenga el mismo problema.
fuente
Puede intentar consultar algunos de los generadores de clase en línea para obtener más información. Sin embargo, creo que algunas de las respuestas han sido útiles. Aquí está mi enfoque que puede ser útil.
El siguiente código fue hecho con un método dinámico en mente.
Este código básicamente le permite acceder a los miembros contenidos en la cadena Json. Simplemente una forma diferente sin la necesidad de las clases.
query
,trend
yurl
son los objetos contenidos en la cadena Json.También puedes usar este sitio web . No confíes en las clases al 100%, pero tienes la idea.
fuente
Suponiendo que sus datos de muestra sean correctos, su nombre de pila y otras entradas entre paréntesis son matrices en JS ... querrá usar Lista para esos tipos de datos. y Lista para decir accountstatusexpmaxdate ... Creo que su ejemplo tiene las fechas incorrectamente formateadas, por lo que no está seguro de qué más es incorrecto en su ejemplo.
Esta es una publicación antigua, pero quería tomar nota de los problemas.
fuente