Jak przekonwertować obiekt JSON na niestandardowy obiekt C #?

247

Czy istnieje prosty sposób na wypełnienie mojego obiektu C # obiektem JSON przekazanym przez AJAX?

Jest to obiekt JSON przekazany do C # WEBMETHOD ze strony przy użyciu JSON.stringify

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

C # WebMetod, który odbiera obiekt JSON

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

}

Klasa C # reprezentująca strukturę obiektową obiektu JSON przekazanego do 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
źródło
69
Chciałbym dodać, że możesz użyć json2csharp.com, aby wygenerować dla Ciebie swoje klasy c #. Pełne ujawnienie: Stworzyłem tę stronę.
JonathanK
Sprawdź ten stackoverflow.com/questions/22191167/…
Pratik Bhoir
@JonathanK Jesteś moim wybawcą!
Matheno,

Odpowiedzi:

218

Dobrym sposobem na użycie JSON w C # jest JSON.NET

Szybki start i dokumentacja API z JSON.NET - oficjalna strona pomaga w pracy z nim.

Przykład, jak z niego korzystać:

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
źródło
5
Działa to jak bohater, ale co, jeśli mam wiele przedmiotów w Jsonie i chcę utworzyć listę obiektów?
Djeroen
@Djeroen: Widzę na to dwa sposoby. Jeśli elementy nie są pogrupowane, spróbuj znaleźć sposób na podzielenie łańcucha, powtórz proces w pętli. Jeśli są zgrupowane, stwórz obiekt obiektów
użytkownik1011138
1
Wolę te linijki wymienione w innych odpowiedziach. IMHO.
RayLoveless,
Tak, to nie jest miłe podejście, poniższe poniżej korzystanie z DeserializeObject jest znacznie czystsze
Andrew
209

Ponieważ wszyscy kochamy jeden kod liniowy

Newtonsoft jest szybszy niż serializator skryptów Java. ... ten zależy od pakietu Newtonsoft NuGet, który jest popularny i lepszy niż domyślny serializator.

jeśli mamy klasę, użyj poniżej.

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

żadna klasa nie używa dynamiki

var oMycustomclassname = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonString);
MSTdev
źródło
95

Aby pozostawić otwarte opcje, jeśli korzystasz z .NET 3.5 lub nowszego, oto zawarty przykład, którego możesz użyć bezpośrednio z frameworka za pomocą Generics. Jak wspomnieli inni, jeśli nie są to tylko proste obiekty, naprawdę powinieneś używać 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;
}

Będziesz potrzebował:

using System.Runtime.Serialization;

using System.Runtime.Serialization.Json;
Jammin
źródło
@ChristianPayne ha! Dobra uwaga, tak, należy je zapakować. Patrząc na to z perspektywy czasu, wystarczy użyć JSON.NET!
Jammin,
2
Jeśli klasa DataContractJsonSerializer nie jest widoczna, musisz dodać odwołanie do System.Runtime.Serialization, klikając prawym przyciskiem myszy Odwołania w rozwiązaniu, wybierz kartę .NET i wybierz System.Runtime.Serialization
DanKodi
1
Jeden scenariusz, w którym ten się psuje. Jeśli obiekt JSON reprezentuje właściwości z pojedynczymi cudzysłowami, funkcja ta kończy się niepowodzeniem. np. nie był w stanie przeanalizować {„Temat”: „E-mail: Dziennik aktywności użytkownika internetowego 11”, „EmbedAsImage”: prawda}, ale nie mógł przeanalizować {„Temat”: „E-mail: Dziennik aktywności użytkownika sieci Web 11”, „EmbedAsImage” : true}
dreamerkumar
Dodatkowo musiałem ozdobić moją prostą klasę atrybutami DataContract i DataMember. Bez tego nie da się parsować.
dreamerkumar
W przeciwieństwie do Vishala klasa POCO działała dla mnie idealnie ... +1, ponieważ pozwala to uniknąć zależności od JSON.NET.
Dunc,
54

Biorąc pod uwagę przykładowy kod, nie powinieneś robić nic więcej.

Jeśli przekażesz ten ciąg JSON do metody internetowej, automatycznie przeanalizuje on ciąg JSON i utworzy zapełniony obiekt użytkownika jako parametr dla metody SaveTeam.

Ogólnie jednak możesz użyć tej JavascriptSerializerklasy, jak poniżej, lub dla większej elastyczności, użyć dowolnego z dostępnych frameworków Json (Jayrock JSON jest dobry) dla łatwej manipulacji JSON.

 JavaScriptSerializer jss= new JavaScriptSerializer();
 User user = jss.Deserialize<User>(jsonResponse); 
womp
źródło
1
Myślę, że musisz użyć niezliczonego typu (więc w tym przykładzie Lista <Użytkownik>)
Dragouf
Jak możemy dokonać deserializacji, jeśli zawiera model widoku pomocniczego
SrinivasNaidu
1
Dla tych, którzy szukają, musisz odwołać się do System.Web.Extensionszestawu i dodać, using System.Web.Script.Serializationaby dostać się do JavaScriptSerializer, ale kiedy to zrobisz, wydaje się to najczystszym sposobem na deserializację swoich jsonciągów w c # konkretnych klas.
Serj Sagan
41

Innym naprawdę prostym rozwiązaniem jest użycie biblioteki Newtonsoft.Json:

User user = JsonConvert.DeserializeObject<User>(jsonString);
Daniel
źródło
ale jeśli obiekt użytkownika ma inne dane JSon we właściwości, to się nie powiedzie ...
gumuruh
@ gumuruh Chyba nie zrozumiałem twojego oświadczenia. Jeśli masz złożony obiekt, którego właściwości są innymi złożonymi obiektami, zostaną one również przekonwertowane, o ile Twój ciąg Json ma poprawnie dane.
Daniel
33

Poniższe 2 przykłady wykorzystują oba

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

Przykład 1: użycie 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
        }
    }
}

Zastosowanie: Obiekt JSON na niestandardowy obiekt C #

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

Przykład 2: użycie 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
        }
    }
}

Zastosowanie: Obiekt JSON na niestandardowy obiekt C #

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

Ten kod wymaga dodania przestrzeni nazw System.Web.Helpers w,

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

Lub

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

Mam nadzieję że to pomoże!


źródło
To bardzo dobra odpowiedź, ale trudna rzecz polega na tym, że w przypadku dynamictypów nie można sprawdzić prawdziwego typu. Na przykład, jeśli Twój JSON zawiera "Name" : "Ahmed"i źle wpisujesz „Nazwa” w kodzie C #, jest to błąd czasu wykonania (bleh).
Jess
Dzięki! Zaktualizuj odpowiedź, aby stwierdzić, że w przykładzie 1 musisz odwołać się do System.Web.Extensions.dll
Valamas,
1
super świetna odpowiedź, dynamiczne pisanie działa również w / 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);
        }
    }
}

Więcej informacji można znaleźć pod następującym linkiem http://ishareidea.blogspot.in/2012/05/json-conversion.html

O DataContractJsonSerializer Classtym możesz przeczytać tutaj .

Deweloper Syam
źródło
5

Korzystanie z JavaScriptSerializer () jest mniej rygorystyczne niż oferowane ogólne rozwiązanie: public static T Deserialize (string json)

Może się to przydać przy przekazywaniu jsona na serwer, który nie odpowiada dokładnie definicji obiektu, na którą próbujesz przekonwertować.

Ioannis Suarez
źródło
1

JSON.Net jest najlepszym rozwiązaniem, ale w zależności od kształtu obiektów i zależności między kołami można użyć JavaScriptSerializer lub DataContractSerializer.

Sky Sanders
źródło
1

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

Serializer kontraktu danych: wymaga using System.Runtime.Serialization.Json; - Ogólny typ T powinien być możliwy do serializacji w większym stopniu na kontrakcie danych

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
źródło
0

Zamiast wysyłać jako przedmiot.

Utwórz publiczną klasę właściwości, która jest dostępna, i wyślij dane do metody internetowej.

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

użyj tych samych nazw parametrów w wywołaniu ajax, aby wysłać dane.

Praveen Kumar Rejeti
źródło