web-dev-qa-db-fra.com

Désérialiser les données JSON en C # à l'aide de JSON.NET

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"
    ]
}
140
user305145

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

272
w.donk

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

77
Dave Swersky

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.

49
biofractal

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.

8
bbants

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");

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.

Xamasoft JSON Class Generator

3
Kyle Falconer

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.

1
Adam

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.

1
Edward Newgate

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.

0
Tracker1