Десеріалізувати JSON за допомогою C #


206

Я намагаюся дезаріалізувати виклик Graph API API друга в список об'єктів. Об'єкт JSON виглядає так:

{"data":[{"id":"518523721","name":"ftyft"},
         {"id":"527032438","name":"ftyftyf"},
         {"id":"527572047","name":"ftgft"},
         {"id":"531141884","name":"ftftft"},
         {"id":"532652067","name"...

List<EFacebook> facebooks = new JavaScriptSerializer().Deserialize<List<EFacebook>>(result);

Це не працює, тому що примітивний об’єкт недійсний. Як я можу це знецінити?


3
напишіть спеціальний десеріалізатор спеціально для задоволення такого json ...
ashutosh raina

2
або ви можете скористатися послугою Dictionary<string,string>, перевірте: stackoverflow.com/questions/7699972/…
Какаші,

9
Ваш друг: json2csharp.com
nawfal

4
Насправді візуальні студії (станом на 2013 або 2012 рік із встановленими веб-інструментами) мають вбудовану точну функціональність: Редагувати> Спеціальна вставка> Вставити JSON As
Class

Відповіді:


264

Вам потрібно створити таку структуру:

public class Friends
{

    public List<FacebookFriend> data {get; set;}
}

public class FacebookFriend
{

    public string id {get; set;}
    public string name {get; set;}
}

Тоді ви повинні мати можливість:

Friends facebookFriends = new JavaScriptSerializer().Deserialize<Friends>(result);

Назви моїх занять - лише приклад. Ви повинні використовувати власні імена.

Додавання зразкового тесту:

string json =
    @"{""data"":[{""id"":""518523721"",""name"":""ftyft""}, {""id"":""527032438"",""name"":""ftyftyf""}, {""id"":""527572047"",""name"":""ftgft""}, {""id"":""531141884"",""name"":""ftftft""}]}";

Friends facebookFriends = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Friends>(json);

foreach(var item in facebookFriends.data)
{
    Console.WriteLine("id: {0}, name: {1}", item.id, item.name);
}

Виробляє:

id: 518523721, name: ftyft
id: 527032438, name: ftyftyf
id: 527572047, name: ftgft
id: 531141884, name: ftftft

3
Так, це те, що я не хочу робити, створити новий об'єкт для утримання дітей. Я думаю, що я буду підстроковувати json, виймаючи примітивний об'єкт. Дякую.

@Kevin Holditch дякую за виправлення. Я пропустив один важливий шматочок :)
Ікар

2
Що мені не подобається в цьому System.Web.Script.Serialization.JavaScriptSerializer () - це те, що вам завжди потрібен визначений тип T. У Java є ця бібліотека (пакет) org.java, яка залишається всім анонімним: "JSONObject [" парам "]. JSONarray (5)" тощо
спорт

2
Важливо зауважити, що параметри для властивостей id та імені повинні залишатися відкритими. Якщо вони встановлені приватними або захищеними, десеріалізація виконається без помилок, але всі дані будуть недійсними.
Ісаак Заїс

2
@sports, ви можете це зробити в C #, деріаріалізуючи до динамічного, але продуктивність набагато краща, якщо ви дезаріалізуєте на відомий тип.
PRMan

50

Іноді я віддаю перевагу динамічним об'єктам:

public JsonResult GetJson()
{
  string res;
  WebClient client = new WebClient();

  // Download string
  string value = client.DownloadString("https://api.instagram.com/v1/users/000000000/media/recent/?client_id=clientId");

  // Write values
  res = value;
  dynamic dyn = JsonConvert.DeserializeObject(res);
  var lstInstagramObjects = new List<InstagramModel>();

  foreach(var obj in dyn.data)
  {
    lstInstagramObjects.Add(new InstagramModel()
    {
      Link = (obj.link != null) ? obj.link.ToString() : "",
      VideoUrl = (obj.videos != null) ? obj.videos.standard_resolution.url.ToString() : "",
      CommentsCount = int.Parse(obj.comments.count.ToString()),
      LikesCount = int.Parse(obj.likes.count.ToString()),
      CreatedTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds((double.Parse(obj.created_time.ToString()))),
      ImageUrl = (obj.images != null) ? obj.images.standard_resolution.url.ToString() : "",
      User = new InstagramModel.UserAccount()
             {
               username = obj.user.username,
               website = obj.user.website,
               profile_picture = obj.user.profile_picture,
               full_name = obj.user.full_name,
               bio = obj.user.bio,
               id = obj.user.id
             }
    });
  }

  return Json(lstInstagramObjects, JsonRequestBehavior.AllowGet);
}

Одного разу прикладом екземпляра, де це було корисно, було те, коли об’єкт, який я намагався десаріалізувати, містив властивість, яка була інтерфейсом
soupy1976,

2
Пояснення було б в порядку.
Пітер Мортенсен

Чому ви віддасте перевагу цьому над прийнятою відповіддю від @Icarus?
Допит

@ Питання, десеріалізація до класів сильних типів нехтуватиме будь-якими властивостями, яких не було у ваших класах, тоді як десеріалізація до динамічних об'єктів просто поверне динамічний. (як я вже казав, іноді не стандартно)
Бішой Ганною

39

Прекрасний спосіб автоматичного генерування цих класів для вас - скопіювати вихід JSON і занести його сюди:

http://json2csharp.com/

Це дасть вам початкову точку для підбору ваших класів для дезаріалізації.


28

Дуже легко ми можемо розібрати вміст JSON за допомогою словника та JavaScriptSerializer. Ось зразок коду, за допомогою якого я аналізую вміст JSON з файлу ashx.

var jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(json);
string _Name = sData["Name"].ToString();
string _Subject = sData["Subject"].ToString();
string _Email = sData["Email"].ToString();
string _Details = sData["Details"].ToString();

3
Це рішення є дуже корисним, якщо у вас немає часу або потрібно створити договори з даними. Особливо, якщо вас цікавить лише кілька атрибутів, похованих глибоко в структурі JSON. У цій ситуації ви можете використовувати серію тверджень, щоб перейти до того, що вам потрібно. Примітка: тип деріаріалізації також може бути одним із наступних: Словник <рядок, об'єкт> або ArrayList (коли вузол має структуру, що повторюється).
Філіп Монне

1
Я отримую виняток із часу запуску із цього: Немає конструктора без параметрів, визначеного для типу 'System.String' у рядку коду Deserialize.
РСК

20

Newtonsoft.JSONє хорошим рішенням для подібних ситуацій. Крім того, Newtonsof.JSONце швидше , ніж інші, наприклад JavaScriptSerializer, DataContractJsonSerializer.

У цьому зразку ви можете:

var jsonData = JObject.Parse("your JSON data here");

Тоді ви можете передавати jsonData JArray, і ви можете використовувати forцикл для отримання даних при кожній ітерації.

Також я хочу додати щось:

for (int i = 0; (JArray)jsonData["data"].Count; i++)
{
    var data = jsonData[i - 1];
}

Робота з динамічним об'єктом та використання серіалізації Newtonsoft - хороший вибір.


15

Я погоджуюся з Icarus (я б прокоментував, якби міг), але замість використання класу CustomObject я використовував би Словник (у випадку, якщо Facebook щось додасть).

private class MyFacebookClass
{
    public IList<IDictionary<string, string>> data { get; set; }
}

або

private class MyFacebookClass
{
    public IList<IDictionary<string, object>> data { get; set; }
}

3
Використання динамічної роботи краще в нових версіях. public IList<IDictionary<string, dynmaic>> data { get; set; }
BJury

3

Серіалізація:

// Convert an object to JSON string format
string jsonData = JsonConvert.SerializeObject(obj);

Response.Write(jsonData);

Десеріалізація: :

Десеріалізувати динамічний об’єкт

  string json = @"{
      'Name': 'name',
      'Description': 'des'
    }";

var res = JsonConvert.DeserializeObject< dynamic>(json);

Response.Write(res.Name);

3

Ви можете використовувати ці розширення

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

1

Ось ще один сайт, який допоможе вам з усім кодом, який вам потрібен, якщо у вас буде правильно сформована рядок JSON:

https://app.quicktype.io/


1

Якщо ви використовуєте .NET Core 3.0, ви можете використовувати System.Text.Json (який зараз вбудований) для десеріалізації JSON.

Перший крок - створення класів для моделювання JSON. Є багато інструментів, які можуть допомогти у цьому, і деякі відповіді тут перераховують їх.

Деякі параметри є http://json2csharp.com , http://app.quicktype.io або використовувати Visual Studio (меню ПравкаСпеціальна вставкаВставити JSON як класи ).

public class Person
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Response
{
    public List<Person> Data { get; set; }
}

Потім ви можете дезаріалізувати, використовуючи:

var people = JsonSerializer.Deserialize<Response>(json);

Якщо вам потрібно додати налаштування, наприклад camelCaseобробку, перенесіть параметри серіалізатора в десеріалізатор таким чином:

var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
var person = JsonSerializer.Deserialize<Response>(json, options);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.