Come convertire l'oggetto JSON in oggetto C # personalizzato?


247

C'è un modo semplice per popolare il mio oggetto C # con l'oggetto JSON passato tramite AJAX?

Questo è l'oggetto JSON passato a C # WEBMETHOD dalla pagina usando JSON.stringify

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

WebMetod C # che riceve l'oggetto JSON

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

}

Classe C # che rappresenta la struttura dell'oggetto di JSON Object passato al WebMethod

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

69
Vorrei aggiungere che puoi usare json2csharp.com per generare le tue classi c # per te. Divulgazione completa: ho creato questo sito.
JonathanK,


@JonathanK Sei il mio salvatore!
Matheno,

Risposte:


218

Un buon modo per usare JSON in C # è con JSON.NET

Avvio rapido e documentazione API da JSON.NET - Il sito ufficiale ti aiuta a lavorare con esso.

Un esempio di come usarlo:

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

5
Funziona come un campione, ma cosa succede se ho più elementi nel mio JSON e voglio fare un elenco di oggetti?
Djeroen,

@Djeroen: vedo due modi per farlo. Se gli elementi non sono raggruppati, prova a trovare un modo per dividere la stringa e ripeti il ​​processo in un ciclo. Se sono raggruppati, crea un oggetto di oggetti
user1011138

1
Preferisco le fodere menzionate in altre risposte .. IMHO.
RayLoveless,

Sì, questo non è un approccio gradevole, quello che segue usando DeserializeObject è molto più pulito
Andrew

209

Dal momento che amiamo tutti un codice di linea

Newtonsoft è più veloce del serializzatore di script java. ... questo dipende dal pacchetto NuGet Newtonsoft, che è popolare e migliore del serializzatore predefinito.

se abbiamo classe, usa di seguito.

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

nessuna classe quindi usa la dinamica

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

95

Per mantenere aperte le opzioni, se si utilizza .NET 3.5 o versioni successive, ecco un esempio completo che è possibile utilizzare direttamente dal framework utilizzando Generics. Come altri hanno già detto, se non sono solo oggetti semplici, dovresti davvero usare 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;
}

Avrai bisogno:

using System.Runtime.Serialization;

using System.Runtime.Serialization.Json;

@ChristianPayne ha! Buon punto, sì, questi dovrebbero essere avvolti. Con il senno di poi, basta usare JSON.NET!
Jammin,

2
Se la classe DataContractJsonSerializer non è visibile, è necessario aggiungere un riferimento a System.Runtime.Serialization facendo clic con il tasto destro del mouse su Riferimenti nella soluzione, selezionare la scheda .NET e selezionare System.Runtime.Serialization
DanKodi

1
Uno scenario in cui questo si interrompe. Se l'oggetto JSON rappresenta proprietà con virgolette singole, questa funzione ha esito negativo. ad esempio, non è stato in grado di analizzare {'Subject': 'Emailing: Web Activity Activity Log11', 'EmbedAsImage': true} ma è stato in grado di analizzare {"Subject": "Emailing: Web User Activity Log11", "EmbedAsImage" : true}
dreamerkumar il

Inoltre, dovevo decorare la mia semplice classe con gli attributi DataContract e DataMember. Non analizzerà senza di essa.
dreamerkumar,

A differenza di Vishal, una classe POCO ha funzionato perfettamente per me ... +1 poiché questo evita una dipendenza da JSON.NET.
Dunc,

54

Dato l'esempio di codice, non dovresti fare nient'altro.

Se si passa quella stringa JSON al metodo Web, analizzerà automaticamente la stringa JSON e creerà un oggetto Utente popolato come parametro per il metodo SaveTeam.

In genere, tuttavia, è possibile utilizzare la JavascriptSerializerclasse come di seguito o, per maggiore flessibilità, utilizzare uno dei vari framework Json disponibili (Jayrock JSON è uno di quelli validi) per una facile manipolazione JSON.

 JavaScriptSerializer jss= new JavaScriptSerializer();
 User user = jss.Deserialize<User>(jsonResponse); 

1
Penso che tu debba usare un tipo ienumerable (quindi in questo esempio Elenco <Utente>)
Dragouf

Come possiamo deserializzare se contiene un modello di visualizzazione secondaria
SrinivasNaidu

1
Per coloro che cercano è necessario fare riferimento System.Web.Extensionsall'assemblaggio e aggiungere un using System.Web.Script.Serializationper ottenere il JavaScriptSerializer, ma una volta fatto, questo sembra il modo più pulito per deserializzare le jsonstringhe in classi concrete.
Serj Sagan,

41

Un'altra soluzione davvero semplice sta usando la libreria Newtonsoft.Json:

User user = JsonConvert.DeserializeObject<User>(jsonString);

ma se l'oggetto Utente ha altri dati JSon nella proprietà, questo fallirà ...
gumuruh,

@gumuruh Immagino di non aver capito la tua affermazione. Se si dispone di un oggetto complesso, le proprietà della strega sono altri oggetti complessi, verranno anch'essi convertiti, a condizione che la stringa Json disponga dei dati correttamente.
Daniel,

33

I seguenti 2 esempi fanno uso di entrambi

  1. JavaScriptSerializer in System.Web.Script.Serialization Or
  2. Json.Decode in System.Web.Helpers

Esempio 1: utilizzo di 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
        }
    }
}

Utilizzo: oggetto JSON su oggetto C # personalizzato

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; }
    }
}

Esempio 2: utilizzo di 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
        }
    }
}

Utilizzo: oggetto JSON su oggetto C # personalizzato

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; }
    }
}

Questo codice richiede l'aggiunta dello spazio dei nomi System.Web.Helpers trovato in,

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

O

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

Spero che questo ti aiuti!


Questa è un'ottima risposta, ma la cosa difficile è che con i dynamictipi, non si ottiene alcun controllo del tipo vero. Ad esempio, se JSON contiene "Name" : "Ahmed"e digitate erroneamente "Nome" nel codice C #, si tratta di un errore di runtime (bleh).
Jess,

Grazie! Aggiorna la risposta per affermare che per l'esempio 1, devi fare riferimento a System.Web.Extensions.dll
Valamas

1
risposta eccellente, la digitazione dinamica funziona anche con 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);
        }
    }
}

Maggiori informazioni vai al seguente link http://ishareidea.blogspot.in/2012/05/json-conversion.html

Chi DataContractJsonSerializer Classpuoi leggere qui .


5

L'uso di JavaScriptSerializer () è meno rigoroso della soluzione generica offerta: T statico pubblico Deserialize (stringa json)

Ciò potrebbe tornare utile quando si passa json al server che non corrisponde esattamente alla definizione dell'oggetto in cui si sta tentando di convertire.



1

JSON.Net è la soluzione migliore ma, a seconda della forma degli oggetti e della presenza di dipendenze circolari, è possibile utilizzare JavaScriptSerializer o DataContractSerializer.



1

Serializer JavaScript: richiede 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);
    }
}

Serializzatore del contratto dati: richiede using System.Runtime.Serialization.Json; : il tipo T generico dovrebbe essere più serializzabile nel contratto dati

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

0

Invece di inviare come solo un oggetto.

Creare una classe pubblica di proprietà accessibile e inviare i dati al metodo Web.

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

usa gli stessi nomi di parametri nella chiamata ajax per inviare dati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.