Как я могу разобрать JSON с C #?


455

У меня есть следующий код:

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

Входные данные в responsecontentформате JSON, но они неправильно проанализированы в объекте. Как мне правильно десериализовать это?


7
Эй, вы можете попробовать эту ссылку techblog.procurios.nl/k/n618/news/view/14605/14863/…
Вамси

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. Если вы думаете, что этого недостаточно, MS придумывает, System.Jsonно в настоящее время не подходит для потребления. Путь в Microsoft Путь в путь .... Я выбираю наиболее привлекательное пространство имен.
nawfal

4
@fusi остальные находятся в отдельных сборках. Google имя пространства / имя класса, вы найдете сборку, они находятся в документации MSDN. Просто добавьте ссылку на эту сборку.
nawfal

1
Просто для завершения, есть также JsonValueв Windows.Data.Jsonкотором только для Windows 8 и выше. Я люблю это. MS находится на миссии :)
nawfal

5
У NewtonSoft есть страница сравнения на их сайте (может быть предвзятой, но все же интересной): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm . Мне особенно понравилась бессмысленная строка сериализации словаря :)
Ohad Schneider

Ответы:


365

Я предполагаю, что вы не используете Json.NET (пакет Newtonsoft.Json NuGet). Если это так, то вы должны попробовать.

Он имеет следующие особенности:

  1. LINQ to 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 User Stories и хочу преобразовать их в объекты.
Педро Дуссо

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 секунды равны 3 с и 703 мс, а разделитель - десятичная точка, я сообщаю вам, что это секунды от трех до десятичного знака.
Питер Воне,

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 ["Name"] "и" stuff ["Address"] ["City"]' соответственно ,
Фил

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/...
Alex

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
С нетерпением ждем вас, чтобы найти эту библиотеку. Изменить: это это: dynamicjson.codeplex.com ?
user989056

1
Я не знаю, что здесь имел в виду класс ElonU, но в Windows.Data.Json есть «JsonValue» (который только для Windows 8 и выше - странный), а также тот же «JsonValue» в System.Json, который все еще находится в режиме предварительного просмотра и Один Бог знает, выйдет ли когда-нибудь. MS смущает меня, когда дело доходит до 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, который является последней версией .NET для Windows XP. Возможна полная установка .NET, но многие придерживаются только профиля клиента. Напротив, System.Runtime.Serialization.Json.DataContractJsonSerializer поддерживается даже в профиле клиента.
Аль Кепп

3
@ fr34kyn01535: Windows XP занимает второе место на рынке среди настольных компьютеров. Это актуально.
DonkeyMaster

Когда я использовал JavaScriptSerializer для десериализации моего объекта, он работал, но неверно десериализовал мою дату. Это должно было быть 4/19/2018 12:00 AM, но десериализовано к 18/04/2018 08:00 PM. 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
Это мне очень помогло. Большое спасибо.
МАК

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

Спасибо, я хотел часть ["result" + variable], потому что я хотел использовать здесь переменные, которые вы не можете легко сделать с JSON.NET.
PHPGuru

Эта строка что-то делает ... JavaScriptSerializer js = new 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

Стоит отметить, что при использовании вашего собственного кода свойства JSON автоматически System.Text.Json не обрабатываются (однако это происходит при использовании запросов MVC / WebAPI и связывателя модели).camelCase

Чтобы решить эту проблему, вам нужно передать 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? Или если ключи существуют вообще?
Черона

@ Черона использовать 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, я не смог найти 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). Затем вы должны использовать это в ASP.NET Web API следующим образом:

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