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.