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

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


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

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

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;

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

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

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!


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 .


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ć.



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.



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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.