Как преобразовать объект JSON в пользовательский объект C #?

247

Есть ли простой способ заполнить мой объект C # объектом JSON, переданным через AJAX?

Это JSON-объект, переданный в C # WEBMETHOD со страницы с использованием JSON.stringify.

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

C # WebMetod, который получает объект JSON

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

}

Класс C #, который представляет структуру объекта JSON Object, переданного в 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
источник
69
Я хотел бы добавить, что вы можете использовать json2csharp.com для генерации ваших классов C # для вас. Полное раскрытие: я создал этот сайт.
JonathanK
Проверьте это stackoverflow.com/questions/22191167/…
Pratik Bhoir
@JonathanK Ты мой спаситель!
Матено

Ответы:

218

Хороший способ использовать JSON в C # - это JSON.NET

Быстрый старт и документация по API от JSON.NET - Официальный сайт поможет вам с ним работать.

Пример того, как его использовать:

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
источник
5
Это работает как чемпион, но что, если у меня есть несколько элементов в моем json, и я хочу создать список объектов?
Джероен
@Djeroen: я вижу два пути для этого. Если элементы не сгруппированы, попробуйте найти способ разбить строку и повторите процесс в цикле. Если они сгруппированы, сделайте объект из объектов
user1011138
1
Я предпочитаю один лайнер, упомянутый в других ответах .. ИМХО.
RayLoveless
Да, это не очень хороший подход, тот, что ниже с использованием DeserializeObject, намного чище
Эндрю
209

Так как мы все любим один код лайнеров

Newtonsoft работает быстрее, чем сериализатор Java-скриптов. ... это зависит от пакета Newtonsoft NuGet, который популярен и лучше, чем стандартный сериализатор.

если у нас есть класс, используйте ниже.

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

нет класса, то использовать динамический

var oMycustomclassname = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(jsonString);
MSTdev
источник
95

Чтобы оставить ваши настройки открытыми, если вы используете .NET 3.5 или более позднюю версию, приведу обобщенный пример, который вы можете использовать прямо из фреймворка, используя Generics. Как уже упоминали другие, если это не просто простые объекты, вы действительно должны использовать 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;
}

Тебе понадобиться:

using System.Runtime.Serialization;

using System.Runtime.Serialization.Json;
Jammin
источник
@ChristianPayne ха! Хороший вопрос, да, они должны быть обернуты. Оглядываясь назад, просто используйте JSON.NET!
Jammin
2
Если класс DataContractJsonSerializer не виден, необходимо добавить ссылку на System.Runtime.Serialization, щелкнув правой кнопкой мыши ссылку «Ссылки» в решении, перейдите на вкладку .NET и выберите System.Runtime.Serialization
DanKodi
1
Один сценарий, где этот ломается. Если ваш объект JSON представляет свойства в одинарных кавычках, эта функция завершается ошибкой. например, он не смог разобрать {'Subject': 'Emailing: журнал активности веб-пользователя', 'EmbedAsImage': true}, но ему удалось проанализировать {"Subject": "Emailing: журнал активности веб-пользователя 11", "EmbedAsImage" : true}
dreamerkumar
Кроме того, мне нужно было украсить свой простой класс атрибутами DataContract и DataMember. Без этого не разберется.
dreamerkumar
В отличие от Вишала, класс POCO отлично сработал для меня ... +1, поскольку это позволяет избежать зависимости от JSON.NET.
Дунк
54

Учитывая ваш пример кода, вам не нужно больше ничего делать.

Если вы передадите эту строку JSON в свой веб-метод, она автоматически проанализирует строку JSON и создаст заполненный объект User в качестве параметра для вашего метода SaveTeam.

Однако, как правило, вы можете использовать JavascriptSerializerкласс, как показано ниже, или для большей гибкости используйте любую из различных сред Json (Jayrock JSON - хорошая) для легкой манипуляции JSON.

 JavaScriptSerializer jss= new JavaScriptSerializer();
 User user = jss.Deserialize<User>(jsonResponse); 
WOMP
источник
1
Я думаю, что вы должны использовать перечисляемый тип (так в этом примере List <User>)
Dragouf
Как мы можем десериализовать, если он содержит модель подвид
SrinivasNaidu
1
Для тех, кто ищет, вам нужно сослаться на System.Web.Extensionsсборку и добавить a, using System.Web.Script.Serializationчтобы получить JavaScriptSerializer, но как только вы это сделаете, это кажется самым чистым способом десериализации ваших jsonстрок в конкретные классы c #.
Серж Саган
41

Другое действительно простое решение - использование библиотеки Newtonsoft.Json:

User user = JsonConvert.DeserializeObject<User>(jsonString);
Даниил
источник
но если у объекта User есть другие данные JSon в свойстве, это не удастся ...
gumuruh
@gumuruh Думаю, я не понял твоего утверждения. Если у вас есть сложный объект, свойства которого являются другими сложными объектами, они также будут преобразованы, если ваша строка Json будет правильно содержать данные.
Даниил
33

Следующие 2 примера используют либо

  1. JavaScriptSerializer под System.Web.Script.Serialization или
  2. Json.Decode под System.Web.Helpers

Пример 1: использование 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
        }
    }
}

Использование: объект JSON для объекта Custom 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; }
    }
}

Пример 2: использование 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
        }
    }
}

Использование: объект JSON для объекта Custom 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; }
    }
}

Этот код требует добавления пространства имен System.Web.Helpers, найденного в

% ProgramFiles% \ Microsoft ASP.NET \ Веб-страницы ASP.NET {ВЕРСИЯ} \ Сборки \ System.Web.Helpers.dll

Или

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

Надеюсь это поможет!


источник
Это очень хороший ответ, но хитрость в том, что с dynamicтипами вы не получаете никакой настоящей проверки типов. Например, если ваш JSON содержит "Name" : "Ahmed"и вы неправильно набрали «Имя» в своем коде на C #, это ошибка времени выполнения (bleh).
Джесс
Спасибо! Пожалуйста, обновите ответ, указав, что для примера 1 вам нужно сослаться на System.Web.Extensions.dll
Valamas
1
супер отличный ответ, динамическая типизация работает также с 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);
        }
    }
}

Более подробную информацию можно найти по следующей ссылке http://ishareidea.blogspot.in/2012/05/json-conversion.html.

О DataContractJsonSerializer Classвы можете прочитать здесь .

Syam Developer
источник
5

Использование JavaScriptSerializer () менее строгое, чем предлагаемое общее решение: public static T Deserialize (string json)

Это может пригодиться при передаче json на сервер, который не совсем соответствует определению объекта, к которому вы пытаетесь преобразовать.

Иоаннис Суарес
источник
1

JSON.Net - ваш лучший выбор, но, в зависимости от формы объектов и наличия круговых зависимостей, вы можете использовать JavaScriptSerializer или DataContractSerializer.

Скай Сандерс
источник
1

Сериализатор JavaScript: требуется 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);
    }
}

Сериализатор контракта данных: требуется using System.Runtime.Serialization.Json; - универсальный тип T должен быть сериализуемым больше в контракте данных

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
источник
0

Вместо того, чтобы отправлять как просто объект.

Создайте общедоступный класс доступных свойств и отправьте данные в веб-метод.

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

использовать те же имена параметров в вызове ajax для отправки данных.

Правин Кумар Реджети
источник