Comment convertir un objet JSON en objet C # personnalisé?

247

Existe-t-il un moyen simple de remplir mon objet C # avec l'objet JSON transmis via AJAX?

Il s'agit de l'objet JSON transmis à C # WEBMETHOD à partir de la page utilisant JSON.stringify

{
    "user": {
        "name": "asdf",
        "teamname": "b",
        "email": "c",
        "players": ["1", "2"]
    }
}

C # WebMetod qui reçoit l'objet JSON

[WebMethod]
public static void SaveTeam(Object user)
{

}

Classe C # qui représente la structure d'objet de l'objet JSON transmis à WebMethod

public class User
{
    public string name { get; set; }
    public string teamname { get; set; }
    public string email { get; set; }
    public Array players { get; set; }
}
MHop
la source
69
Je voudrais ajouter que vous pouvez utiliser json2csharp.com pour générer vos classes c # pour vous. Divulgation complète: j'ai créé ce site.
JonathanK
Consultez ce stackoverflow.com/questions/22191167/…
Pratik Bhoir
@JonathanK Tu es mon sauveur!
Matheno

Réponses:

218

Un bon moyen d'utiliser JSON en C # est avec JSON.NET

Démarrages rapides et documentation API de JSON.NET - Site officiel vous aide à travailler avec.

Un exemple d'utilisation:

public class User
{
    public User(string json)
    {
        JObject jObject = JObject.Parse(json);
        JToken jUser = jObject["user"];
        name = (string) jUser["name"];
        teamname = (string) jUser["teamname"];
        email = (string) jUser["email"];
        players = jUser["players"].ToArray();
    }

    public string name { get; set; }
    public string teamname { get; set; }
    public string email { get; set; }
    public Array players { get; set; }
}

// Use
private void Run()
{
    string json = @"{""user"":{""name"":""asdf"",""teamname"":""b"",""email"":""c"",""players"":[""1"",""2""]}}";
    User user = new User(json);

    Console.WriteLine("Name : " + user.name);
    Console.WriteLine("Teamname : " + user.teamname);
    Console.WriteLine("Email : " + user.email);
    Console.WriteLine("Players:");

    foreach (var player in user.players)
        Console.WriteLine(player);
 }
AndreyAkinshin
la source
5
Cela fonctionne comme un champion, mais que se passe-t-il si j'ai plusieurs éléments dans mon json et que je veux créer une liste d'objets?
Djeroen
@ Djeroen: Je vois deux façons pour cela. Si les éléments ne sont pas groupés, essayez de trouver un moyen de diviser la chaîne et répétez le processus en boucle. S'ils sont regroupés, créez un objet d'objets
user1011138
1
Je préfère les doublures mentionnées dans d'autres réponses .. À mon humble avis.
RayLoveless
Oui, ce n'est pas une bonne approche, celle ci-dessous utilisant DeserializeObject est beaucoup plus propre
Andrew
208

Puisque nous aimons tous un code de doublures

Newtonsoft est plus rapide que le sérialiseur de script java. ... celui-ci dépend du package Newtonsoft NuGet, qui est populaire et meilleur que le sérialiseur par défaut.

si nous avons de la classe, utilisez ci-dessous.

Mycustomclassname oMycustomclassname = Newtonsoft.Json.JsonConvert.DeserializeObject<Mycustomclassname>(jsonString);

pas de classe, puis utilisez dynamique

var oMycustomclassname = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonString);
MSTdev
la source
95

Pour garder vos options ouvertes, si vous utilisez .NET 3.5 ou version ultérieure, voici un exemple résumé que vous pouvez utiliser directement à partir du framework à l'aide de Generics. Comme d'autres l'ont mentionné, s'il ne s'agit pas seulement d'objets simples, vous devriez vraiment utiliser JSON.net.

public static string Serialize<T>(T obj)
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    MemoryStream ms = new MemoryStream();
    serializer.WriteObject(ms, obj);
    string retVal = Encoding.UTF8.GetString(ms.ToArray());
    return retVal;
}

public static T Deserialize<T>(string json)
{
    T obj = Activator.CreateInstance<T>();
    MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    obj = (T)serializer.ReadObject(ms);
    ms.Close();
    return obj;
}

Tu auras besoin:

using System.Runtime.Serialization;

using System.Runtime.Serialization.Json;
Jammin
la source
@ChristianPayne ha! Bon point, oui ceux-ci devraient être emballés. Avec du recul, utilisez simplement JSON.NET!
Jammin
2
Si la classe DataContractJsonSerializer n'est pas visible, vous devez ajouter une référence à System.Runtime.Serialization en cliquant avec le bouton droit sur les références dans la solution, sélectionnez l'onglet .NET et sélectionnez System.Runtime.Serialization
DanKodi
1
Un scénario où celui-ci casse. Si votre objet JSON représente des propriétés avec des guillemets simples, cette fonction échoue. Par exemple, il n'a pas pu analyser {'Subject': 'Emailing: Web User Activity Log11', 'EmbedAsImage': true} mais il a pu analyser {"Subject": "Emailing: Web User Activity Log11", "EmbedAsImage" : true}
dreamerkumar
De plus, je devais décorer ma classe simple avec les attributs DataContract et DataMember. Il ne sera pas analysé sans cela.
dreamerkumar
Contrairement à Vishal, une classe POCO a parfaitement fonctionné pour moi ... +1 car cela évite une dépendance à JSON.NET.
Dunc
54

Compte tenu de votre exemple de code, vous ne devriez rien faire d'autre.

Si vous transmettez cette chaîne JSON à votre méthode Web, elle analysera automatiquement la chaîne JSON et créera un objet utilisateur rempli en tant que paramètre de votre méthode SaveTeam.

Cependant, en règle générale, vous pouvez utiliser la JavascriptSerializerclasse comme ci-dessous, ou pour plus de flexibilité, utilisez l'un des divers cadres Json (Jayrock JSON est un bon) pour une manipulation JSON facile.

 JavaScriptSerializer jss= new JavaScriptSerializer();
 User user = jss.Deserialize<User>(jsonResponse); 
womp
la source
1
Je pense que vous devez utiliser un type ienumerable (donc dans cet exemple List <User>)
Dragouf
Comment pouvons-nous désérialiser s'il contient un modèle de vue secondaire
SrinivasNaidu
1
Pour ceux qui cherchent, vous devez référencer l' System.Web.Extensionsassembly et ajouter un using System.Web.Script.Serializationpour y accéder JavaScriptSerializer, mais une fois que vous le faites, cela semble être le moyen le plus propre de désérialiser vos jsonchaînes en classes concrètes c #.
Serj Sagan
41

Une autre solution vraiment simple utilise la bibliothèque Newtonsoft.Json:

User user = JsonConvert.DeserializeObject<User>(jsonString);
Daniel
la source
mais si l'objet User a une autre donnée JSon dans la propriété, cela échouera ...
gumuruh
@gumuruh Je suppose que je n'ai pas compris votre déclaration. Si vous avez un objet complexe dont les propriétés sont un autre objet complexe, elles seront également converties, tant que votre chaîne Json aura les données correctement.
Daniel
33

Les 2 exemples suivants utilisent soit

  1. JavaScriptSerializer sous System.Web.Script.Serialization ou
  2. Json.Decode sous System.Web.Helpers

Exemple 1: utilisation de System.Web.Script.Serialization

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Script.Serialization;

namespace Tests
{
    [TestClass]
    public class JsonTests
    {
        [TestMethod]
        public void Test()
        {
            var json = "{\"user\":{\"name\":\"asdf\",\"teamname\":\"b\",\"email\":\"c\",\"players\":[\"1\",\"2\"]}}";
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            dynamic jsonObject = serializer.Deserialize<dynamic>(json);

            dynamic x = jsonObject["user"]; // result is Dictionary<string,object> user with fields name, teamname, email and players with their values
            x = jsonObject["user"]["name"]; // result is asdf
            x = jsonObject["user"]["players"]; // result is object[] players with its values
        }
    }
}

Utilisation: objet JSON en objet C # personnalisé

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Script.Serialization;
using System.Linq;

namespace Tests
{
    [TestClass]
    public class JsonTests
    {
        [TestMethod]
        public void TestJavaScriptSerializer()
        {
            var json = "{\"user\":{\"name\":\"asdf\",\"teamname\":\"b\",\"email\":\"c\",\"players\":[\"1\",\"2\"]}}";
            User user = new User(json);
            Console.WriteLine("Name : " + user.name);
            Console.WriteLine("Teamname : " + user.teamname);
            Console.WriteLine("Email : " + user.email);
            Console.WriteLine("Players:");
            foreach (var player in user.players)
                Console.WriteLine(player);
        }
    }

    public class User {
        public User(string json) {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            var jsonObject = serializer.Deserialize<dynamic>(json);
            name = (string)jsonObject["user"]["name"];
            teamname = (string)jsonObject["user"]["teamname"];
            email = (string)jsonObject["user"]["email"];
            players = jsonObject["user"]["players"];
        }

        public string name { get; set; }
        public string teamname { get; set; }
        public string email { get; set; }
        public Array players { get; set; }
    }
}

Exemple 2: utilisation de System.Web.Helpers

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Helpers;

namespace Tests
{
    [TestClass]
    public class JsonTests
    {
        [TestMethod]
        public void TestJsonDecode()
        {
            var json = "{\"user\":{\"name\":\"asdf\",\"teamname\":\"b\",\"email\":\"c\",\"players\":[\"1\",\"2\"]}}";
            dynamic jsonObject = Json.Decode(json);

            dynamic x = jsonObject.user; // result is dynamic json object user with fields name, teamname, email and players with their values
            x = jsonObject.user.name; // result is asdf
            x = jsonObject.user.players; // result is dynamic json array players with its values
        }
    }
}

Utilisation: objet JSON en objet C # personnalisé

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Helpers;
using System.Linq;

namespace Tests
{
    [TestClass]
    public class JsonTests
    {
        [TestMethod]
        public void TestJsonDecode()
        {
            var json = "{\"user\":{\"name\":\"asdf\",\"teamname\":\"b\",\"email\":\"c\",\"players\":[\"1\",\"2\"]}}";
            User user = new User(json);
            Console.WriteLine("Name : " + user.name);
            Console.WriteLine("Teamname : " + user.teamname);
            Console.WriteLine("Email : " + user.email);
            Console.WriteLine("Players:");
            foreach (var player in user.players)
                Console.WriteLine(player);
        }
    }

    public class User {
        public User(string json) {
            var jsonObject = Json.Decode(json);
            name = (string)jsonObject.user.name;
            teamname = (string)jsonObject.user.teamname;
            email = (string)jsonObject.user.email;
            players = (DynamicJsonArray) jsonObject.user.players;
        }

        public string name { get; set; }
        public string teamname { get; set; }
        public string email { get; set; }
        public Array players { get; set; }
    }
}

Ce code nécessite l'ajout de l'espace de noms System.Web.Helpers trouvé dans,

% ProgramFiles% \ Microsoft ASP.NET \ Pages Web ASP.NET {VERSION} \ Assemblies \ System.Web.Helpers.dll

Ou

% ProgramFiles (x86)% \ Microsoft ASP.NET \ ASP.NET Web Pages {VERSION} \ Assemblies \ System.Web.Helpers.dll

J'espère que cela t'aides!


la source
C'est une très bonne réponse, mais la chose délicate est qu'avec les dynamictypes, vous n'obtenez pas de véritable vérification de type. Par exemple, si votre JSON contient "Name" : "Ahmed"et que vous tapez mal "Nom" dans votre code C #, c'est une erreur d'exécution (bleh).
Jess
Merci! Veuillez mettre à jour la réponse pour indiquer que pour l'exemple 1, vous devez référencer System.Web.Extensions.dll
Valamas
1
super bonne réponse, la frappe dynamique fonctionne aussi avec json.net v6.0.6!
stackuser83
7
public static class Utilities
{
    public static T Deserialize<T>(string jsonString)
    {
        using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
        {    
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            return (T)serializer.ReadObject(ms);
        }
    }
}

Plus d'informations sur le lien suivant http://ishareidea.blogspot.in/2012/05/json-conversion.html

A propos , DataContractJsonSerializer Classvous pouvez lire ici .

Développeur Syam
la source
5

L'utilisation de JavaScriptSerializer () est moins stricte que la solution générique proposée: public static T Deserialize (string json)

Cela peut être utile lorsque vous transmettez json au serveur qui ne correspond pas exactement à la définition d'objet que vous essayez de convertir.

Ioannis Suarez
la source
1

JSON.Net est votre meilleur pari mais, selon la forme des objets et s'il existe des dépendances circulaires, vous pouvez utiliser JavaScriptSerializer ou DataContractSerializer.

Sky Sanders
la source
1

Sérialiseur JavaScript: nécessite using System.Web.Script.Serialization;

public class JavaScriptSerializerDeSerializer<T>
{
    private readonly JavaScriptSerializer serializer;

    public JavaScriptSerializerDeSerializer()
    {
        this.serializer = new JavaScriptSerializer();
    }

    public string Serialize(T t)
    {
        return this.serializer.Serialize(t);
    }

    public T Deseralize(string stringObject)
    {
        return this.serializer.Deserialize<T>(stringObject);
    }
}

Sérialiseur de contrat de données: nécessite using System.Runtime.Serialization.Json; - Le type générique T doit être sérialisable davantage sur le contrat de données

public class JsonSerializerDeserializer<T> where T : class
{
    private readonly DataContractJsonSerializer jsonSerializer;

    public JsonSerializerDeserializer()
    {
        this.jsonSerializer = new DataContractJsonSerializer(typeof(T));
    }

    public string Serialize(T t)
    {
        using (var memoryStream = new MemoryStream())
        {
            this.jsonSerializer.WriteObject(memoryStream, t);
            memoryStream.Position = 0;
            using (var sr = new StreamReader(memoryStream))
            {
                return sr.ReadToEnd();
            }
        }
    }

    public T Deserialize(string objectString)
    {
        using (var ms = new MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes((objectString))))
        {
            return (T)this.jsonSerializer.ReadObject(ms);
        }
    }
}
BTE
la source
0

Plutôt que d'envoyer comme un simple objet.

Créez une classe publique de propriétés accessible et envoyez les données à la méthode Web.

[WebMethod]
public static void SaveTeam(useSomeClassHere user)
{
}

utilisez les mêmes noms de paramètres dans l'appel ajax pour envoyer des données.

Praveen Kumar Rejeti
la source