Je suis relativement nouveau à l’utilisation des données C # et JSON et je cherche des conseils. J'utilise C # 3.0, avec .NET3.5SP1 et JSON.NET 3.5r6.
J'ai une classe C # définie que je dois renseigner à partir d'une structure JSON. Toutefois, chaque structure JSON d'une entrée extraite du service Web ne contient pas tous les attributs possibles définis dans la classe C #.
Je suis en train de faire ce qui semble être le mauvais chemin, en sélectionnant chaque valeur une à une dans l'objet JO et en transformant la chaîne en propriété de la classe souhaitée.
JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);
MyAccount.EmployeeID = (string)o["employeeid"][0];
Quel est le meilleur moyen de désérialiser une structure JSON dans la classe C # et de gérer les éventuelles données manquantes à partir de la source JSON?
Ma classe est définie comme:
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; }
}
Et un exemple de JSON à analyser est:
{
"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"
]
}
Utilisation
var rootObject = JsonConvert.DeserializeObject<RootObject>(string json);
Créez vos classes sur JSON 2 C #
Documentation Json.NET: Sérialisation et désérialisation JSON avec Json.NET
Avez-vous essayé d'utiliser la méthode générique DeserializeObject?
JsonConvert.DeserializeObject<MyAccount>(myjsondata);
Tous les champs manquants dans les données JSON doivent simplement être laissés à NULL.
MISE À JOUR:
Si la chaîne JSON est un tableau, essayez ceci:
var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);
jarray
devrait alors être un List<MyAccount>
.
Une autre mise à jour:
L'exception que vous obtenez n'est pas compatible avec un tableau d'objets. Je pense que le sérialiseur a des problèmes avec votre propriété accountstatusmodifiedby
de type Dictionary.
Essayez d'exclure de la sérialisation la propriété accountstatusmodifiedby
et voyez si cela vous aide. Si tel est le cas, vous devrez peut-être représenter cette propriété différemment.
Documentation: Sérialisation et désérialisation JSON avec Json.NET
Réponse reproduite de https://stackoverflow.com/a/10718128/776476
Vous pouvez utiliser le type C # dynamic
pour simplifier les choses. Cette technique simplifie également la reconfiguration car elle ne repose pas sur des chaînes magiques.
Json
La chaîne json
ci-dessous est une réponse simple issue d'un appel http api et définit deux propriétés: Id
et Name
.
{"Id": 1, "Name": "biofractal"}
C #
Utilisez JsonConvert.DeserializeObject<dynamic>()
pour désérialiser cette chaîne en un type dynamique, puis accédez simplement à ses propriétés de la manière habituelle.
var results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;
Note : Le lien NuGet pour l’Assemblée NewtonSoft est http://nuget.org/packages/newtonsoft.json . N'oubliez pas d'ajouter: using Newtonsoft.Json;
pour accéder à ces classes.
Vous pouvez utiliser:
JsonConvert.PopulateObject(json, obj);
ici: json
est la chaîne json, obj
est l'objet cible. Voir: exemple
Remarque: PopulateObject()
n'effacera pas les données de la liste obj. Après Populate()
, le membre de la liste obj's
contiendra ses données d'origine et les données de la chaîne json.
S'appuyant sur la réponse de bbant, voici ma solution complète pour la désérialisation de JSON à partir d'une URL distante.
using Newtonsoft.Json;
using System.Net.Http;
namespace Base
{
public class ApiConsumer<T>
{
public T data;
private string url;
public CalendarApiConsumer(string url)
{
this.url = url;
this.data = getItems();
}
private T getItems()
{
T result = default(T);
HttpClient client = new HttpClient();
// This allows for debugging possible JSON issues
var settings = new JsonSerializerSettings
{
Error = (sender, args) =>
{
if (System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
}
};
using (HttpResponseMessage response = client.GetAsync(this.url).Result)
{
if (response.IsSuccessStatusCode)
{
result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings);
}
}
return result;
}
}
}
L'utilisation serait comme:
ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script");
Où FeedResult
est la classe générée à l'aide du Générateur de classes JSON Xamasoft
Voici une capture d'écran des paramètres que j'ai utilisés, permettant des noms de propriété étranges que version Web ne pouvait pas prendre en compte.
J'ai trouvé que j'avais construit mon objet de manière incorrecte. J'ai utilisé http://json2csharp.com/ pour me générer ma classe d'objet à partir du JSON. Une fois que j'ai eu le bon Oject, j'ai pu lancer sans problème. Norbit, erreur Noob. Je pensais l'ajouter au cas où vous auriez le même problème.
Vous pouvez essayer de vérifier en ligne certains des générateurs de classe pour plus d'informations. Cependant, je pense que certaines des réponses ont été utiles. Voici mon approche qui peut être utile.
Le code suivant a été créé avec une méthode dynamique à l’esprit.
dynObj = (JArray)JsonConvert.DeserializeObject(nvm);
foreach (JObject item in dynObj)
{
foreach (JObject trend in item["trends"])
{
Console.WriteLine("{0}-{1}-{2}", trend["query"], trend["name"], trend["url"]);
}
}
Ce code vous permet fondamentalement d'accéder aux membres contenus dans la chaîne Json. Juste une manière différente sans avoir besoin des cours. query
, trend
et url
sont les objets contenus dans la chaîne Json.
Vous pouvez également utiliser ce site . Ne faites pas confiance aux classes à 100% mais vous avez l’idée.
En supposant que vos exemples de données soient corrects, votre nom de groupe et les autres entrées encadrées entre parenthèses sont des tableaux dans JS ... vous voudrez utiliser List pour ces types de données. et List for say accountstatusexpmaxdate ... Je pense que votre exemple contient des dates incorrectement formatées, si incertaines quant à ce qui est incorrect dans votre exemple.
Ceci est un ancien post, mais je voulais prendre note des problèmes.