Як я можу розібрати JSON за допомогою C #?


455

У мене є такий код:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

Вхід в responsecontentJSON, але він неправильно проаналізований в об'єкт. Як я повинен правильно десеріалізувати його?


7
Гей , ви можете спробувати це посилання techblog.procurios.nl/k/n618/news/view/14605/14863 / ...
Vamsi

34
Там же Jsonв System.Web.Helpers, є JsonQueryStringConverterв System.ServiceModel.Web, є JavascriptSerializerв System.Web.Script.Serialization, DataContractJsonSerializerв System.Runtime.Serialization.Json, рис MS навіть вирішив включити третю сторону Json.NETв ASP.NET Web API. Якщо ви думаєте, що цього недостатньо, МС придумує, System.Jsonале наразі непридатний для споживання. Шлях, який потрібно пройти в Microsoft .... Я вибираю найкраще простір імен.
nawfal

4
@fusi решта - в окремих складах. Google простір імен / ім'я класу, ви знайдете збірку, яку вони містять у документації msdn. Просто додайте посилання на цю збірку.
nawfal

1
Просто повна, є і JsonValueв Windows.Data.Jsonякому тільки для Windows 8 і вище. Я люблю його. MS
відправляється

5
NewtonSoft має сторінку порівняння на своєму сайті (може бути упередженою, але все ж цікавою): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm . Особливо мені сподобався рядок серіалізації безглуздого словника :)
Охад Шнайдер

Відповіді:


365

Я припускаю, що ви не використовуєте Json.NET (пакет Newtonsoft.Json NuGet). Якщо це так, то слід спробувати.

Він має такі особливості:

  1. LINQ до JSON
  2. JsonSerializer для швидкого перетворення ваших .NET-об'єктів у JSON і назад
  3. Json.NET може додатково виробляти добре відформатований, з відступом JSON для налагодження або відображення
  4. Атрибути, такі як JsonIgnore та JsonProperty, можна додати до класу, щоб налаштувати спосіб серіалізації класу
  5. Можливість конвертувати JSON в XML і з нього
  6. Підтримується кілька платформ: .NET, Silverlight та Compact Framework

Подивіться на приклад нижче. У цьому прикладі JsonConvertклас використовується для перетворення об'єкта в JSON і з нього. Для цього є два статичні методи. Вони є SerializeObject(Object obj)і DeserializeObject<T>(String json):

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);

18
Чи можу я десеріалізуватися до varзмінної типу, якщо я не знаю повної структури моєї цілі? Зокрема, я споживаю історії користувачів Rally, і хочу перетворити їх на об'єкти.
Педро Дуссо

16
@VANDERWEYENJonathan - у сучасному веб-браузері JSON.parse (рядок) та JSON.stringify (об'єкт) обидва обробляють дати у вигляді рядків ISO8601, що є форматом, зображеним у наведеній вище відповіді. Ви можете оновити свій стандарт, перш ніж люди вирішать, що це не має значення. Люди потребують побачень набагато більше, ніж вони потребують вашого стандарту.
Пітер Вун

3
@PeterWone: Ні, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expiryповертає рядок "2008-12-28T00:00:00" , а не дату. він може бути перетворений вDate через new Date(str), але JSON.parseнічого не знає про дати. Вам доведеться передати відроджувач, який перевіряв кожне значення рядка на зразок.
TJ Crowder

3
Оскільки 3.703 секунди - це 3s і 703ms, а роздільник є десятковою точкою, я вважаю, що це секунди до трьох знаків після коми.
Peter Wone

38
Чому все є така проблема з включенням відповідних require, include, importабо usingзаяви в своїх відповідях. Чи зачепила б ця одна лінія?
Томаш Зато - Відновити Моніку

285

Як тут відповіли - Десеріалізувати JSON в динамічний об'єкт C #?

За допомогою Json.NET це досить просто:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Або за допомогою Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

13
@MaxHodges, ти маєш рацію. Я просто використовував вбудовані "магічні рядки" для демонстрації того, як розбирати значення рядка JSON. Не хотілося, щоб це виглядало складно з уникнутими подвійними цитатами. У реальному коді у нас зазвичай є рядки JSON, отримані десь як змінні або передані як параметри.
Дмитро Павлов

4
Без .net 4 у вас немає ключового слова "динамічний". Ви можете використовувати 'var stuff' для декларування, а замість 'stuff.Name' та 'stuff.Address.City' у вас є 'stuff ["Ім'я"] "та" stuff ["Адреса"] ["Місто"] "відповідно .
Філ

1
@Fil Це дає значення типу object, і ви не можете використовувати індексацію на a object.
Алекс

138

Ось кілька варіантів без використання сторонніх бібліотек:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

Дивіться посилання для отримання додаткової інформації про System.Web.Helpers.Json .

Оновлення : На сьогодні найпростішим способом отримати Web.Helpersє використання пакету NuGet .


Якщо ви не переймаєтесь ранішими версіями Windows, ви можете використовувати класи Windows.Data.Jsonпростору імен:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());

Чому я не бачу System.Web.Helpers на своєму веб-сайті ASP.NET (4.5)? XElement, XPathSelectElement не відомі моїм VisualStudio. Як це виховати?
Будда

Ну, ви повинні додати посилання на відповідні бібліотеки (як написано в коментарях вище), для отримання додаткової інформації дивіться цю статтю . Також це питання може зацікавити.
qqbenq

2
Я використовував описаний тут метод Web.Helpers, але зіткнувся з проблемою, вирішеною цією публікацією: stackoverflow.com/questions/7066726/…
Алекс

1
він працює з WPF.By, використовуючи наступний простір імен за допомогою System.Runtime.Serialization.Json; використовуючи System.Xml.XPath; використовуючи System.Xml.Linq;
Шахід Неермунда


62

Якщо вам доступна .NET 4, перевірте: http://visitmix.com/writings/the-rise-of-json (archive.org)

Ось фрагмент із цього сайту:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

Ця остання Console.WriteLine дуже мила ...


Вибачте, схоже, що змінилися речі з моменту, коли я відповів спочатку. Мені доведеться озирнутися і побачити, яка бібліотека є правильною ...
ElonU Webdev

7
З нетерпінням чекаю, коли ви знайдете цю бібліотеку. Редагувати: це такий: dinamijson.codeplex.com ?
user989056

1
Я не знаю, що тут мав на увазі клас ElonU, але є "JsonValue" в Windows.Data.Json (який є лише для Windows 8 і вище - дивно), а також той самий "JsonValue" у System.Json, який досі переглядається та Сам Бог знає, чи вийде коли-небудь. МС плутає мене, коли йдеться про Джсона.
nawfal

35

Ще одне власне рішення цього питання, яке не потребує сторонніх бібліотек, а посилання на System.Web.Extensions - JavaScriptSerializer. Це не нові, але дуже невідомі вбудовані функції, починаючи з 3.5.

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

і назад

MyObject o = serializer.Deserialize<MyObject>(objectString)

2
Це дуже приємно, але йому потрібні веб-сайти, тому, на жаль, він не працює у .NET 4.0 Client Profile, що є останньою версією .NET для Windows XP. Повна інсталяція .NET можлива, але багато людей дотримуються лише профілю клієнта. На відміну від цього, System.Runtime.Serialization.Json.DataContractJsonSerializer підтримується навіть у профілі клієнта.
Al Kepp

3
@ fr34kyn01535: Windows XP займає друге місце за розмірами на ринку на робочому столі. Це актуально.
DonkeyMaster

Коли я використовував JavaScriptSerializer для десериалізації мого об’єкта, він працював, але він дезаріалізував мою дату неправильно. Це мало бути 19.04.2018 12:00, але дезаріалізоване до 18.04.2018 20:00. NewtonSoft.Json.JsonConvert десеріалізував це як очікувалося.
Багатий


16

System.Json працює зараз ...

Встановіть nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Зразок :

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

1
Спроба знайти приклад того, як правильно використовувати сучасний System.Json привела мене сюди, після незліченних результатів для Json.NET/Newtonsoft.Json/"Newtson.Json "та старих ітерацій System.Json давно застаріла. Дякую за це.
monkey0506

1
Це мені дуже допомогло. Дуже дякую.
MAK

10

Використовуйте цей інструмент для створення класу на базі вашого json:

http://json2csharp.com/

А потім використовуйте клас, щоб десаріалізувати свій json. Приклад:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': 'james@example.com',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// james@example.com

Посилання: https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+using+that+object https://www.newtonsoft.com/json/help /html/DeserializeObject.htm


9

Спробуйте наступний код:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}

Дякую, я хотів частину ["результат" + змінна], тому що я хотів тут використовувати змінні, які ви не можете легко зробити з JSON.NET.
PHPGuru

Чи робить цей рядок щось ... JavaScriptSerializer js = новий JavaScriptSerializer (); Заздалегідь спасибі.
Кріс Катіньяні

9

System.Text.Json

.NET core 3.0 оснащений System.Text.Jsonвбудованою формою, що означає, що ви можете десеріалізувати / серіалізувати JSON, не використовуючи сторонні бібліотеки.

Щоб серіалізувати свої класи до рядка JSON:

var json = JsonSerializer.Serialize(order);

Щоб десаріалізувати JSON в сильно набраний клас:

var order = JsonSerializer.Deserialize<Order>(json);

Тож якщо у вас клас, як показано нижче:

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public decimal Balance { get; set; }
    public DateTime Opened { get; set; }
}

var json = JsonSerializer.Serialize(order);
// creates JSON ==>
{
    "id": 123456,
    "orderNumber": "ABC-123-456",
    "balance": 9876.54,
    "opened": "2019-10-21T23:47:16.85",
};

var order = JsonSerializer.Deserialize<Order>(json);
// ==> creates the above class

Слід зазначити, що автоматично System.Text.Json не обробляє camelCaseвластивості JSON під час використання власного коду (однак це відбувається при використанні запитів MVC / WebAPI та в’яжучої моделі).

Щоб вирішити це, вам потрібно передати JsonSerializerOptionsяк параметр.

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json також доступний для .Net Framework та .Net Standard як пакет Nu-get System.Text.Json


1
Що робити, якщо у вас немає класу? Що робити, якщо ви лише смутно знаєте, що містять дані json? Або якщо ключі взагалі існують?
Черона

@Cherona використання JsonDocument.Parse.
haldo

5

Наведене нижче з сайту msdn, чи варто вважати, що допоможе надати певну функціональність для того, що ви шукаєте. Зверніть увагу, що він вказаний для Windows 8. Один такий приклад із сайту наведено нижче.

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

Він використовує простір імен Windows.Data.JSON .


6
Приємний, але "Мінімально підтримуваний клієнт: Windows 8"
watbywbarif

Я думаю, що його більше не підтримують, і тепер є newtonsoft json dll icouldnt знайти windows.data.json
virtouso

3
@virtouso, як зазначив watbywbarif, це насправді досить нова, однак мінімальна підтримка від Microsoft , працює лише в Windows 8.
TargetofGravity

4

Можна використовувати наступні розширення

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}

0

Я думаю, що найкраща відповідь, яку я бачив, була @MD_Sayem_Ahmed.

Ваше запитання - "Як я можу розібрати Json за допомогою C #", але здається, ви хочете розшифрувати Json. Якщо ви хочете його розшифрувати, відповідь Ахмеда хороша.

Якщо ви намагаєтеся досягти цього в ASP.NET Web Api, найпростішим способом є створення об’єкта передачі даних, який містить дані, які ви хочете призначити:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

Ви просто додали заголовок application / json до свого запиту (наприклад, якщо ви використовуєте Fiddler). Потім ви використовуєте це у веб-API ASP.NET таким чином:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

Це мені дуже допомогло, коли я працював у своєму веб-апі і зробив своє життя дуже легким.


0
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();

-1
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);

2
Ви краще поясніть своє рішення, а не просто розміщувати якийсь рядок коду. Ви можете прочитати Як написати гарну відповідь .
Массіміліано Краус

Не забудьте включити System.Webу свій проект посилання.
Охад Коен

-3
 using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
 {
    // Deserialization from JSON  
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
    DataContractJsonSerializer(typeof(UserListing));
    UserListing response = (UserListing)deserializer.ReadObject(ms);

 }

 public class UserListing
 {
    public List<UserList> users { get; set; }      
 }

 public class UserList
 {
    public string FirstName { get; set; }       
    public string LastName { get; set; } 
 }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.