Json и C#.

  • Михаил
  • 12 мин. на прочтение
  • 96
  • 12 Dec 2012
  • 12 Dec 2012

Json - формат передачи данных, который буквально за несколько лет стал вровень с XML, а в некоторых аспектах даже перегнал его. Facebook, Twitter, и многие популярные сервисы используют этот формат для выдачи данных в своих API.

Существует куча сторонних библиотек для работы с Json в .net, но зачем пользоваться сторонними продуктами, если в .net присутствует всё необходимое для этих целей.

Для примера будем использовать такой Json:

{ 
   "firstName": "Иван", 
   "lastName": "Иванов", 
   "address": { 
     "streetAddress": "Московское ш., 101, кв.101", 
     "city": "Ленинград", 
     "postalCode": 101101 
   }, 
   "phoneNumbers": [ 
     "812 123-1234", 
     "916 123-4567" 
   ] 
} 

Как видите, имеется некая информация о человеке: имя, фамилия, адрес, и его контактные телефоны. При работе с Json, данные могут сериализовываться/десериализовываться. То есть, любой класс описанный в C# мы свободно можем сериализовать и получить чистый Json. Десериализация работает по-другому: на входе у нас имеется Json, а на выходе должен получиться экземпляр класса, со свойствами описанными в Json. Естественно, что этот класс должен быть перед десериализацией подобающим образом определён.

Опишем класс Person:
 

public class Person 
   { 
     public string firstName { get; set; } 
     public string lastName { get; set; } 
     public Address address { get; set; } 
     public string[] phoneNumbers { get; set; } 
     public class Address 
     { 
       public string streetAddress { get; set; } 
       public string city { get; set; } 
       public int postalCode { get; set; } 
     } 
   } 

Как видите, свойства класса должны соответствовать полям, что находятся в Json.

Для работы с Json необходимо подключить Reference System.Runtime.Serialization. Там находится пространство имён Json, его и будем использовать. Нам нужен класс DataContractJsonSerializer. Код для десериализции будет следующий:

 using System.Runtime.Serialization.Json; 
 ...
  private void ParseBtn_Click(object sender, EventArgs e) 
     {       
       DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Person)); 
       string fileContent=System.IO.File.ReadAllText("json.txt"); 
       Person person = (Person)json.ReadObject(new System.IO.MemoryStream(Encoding.UTF8.GetBytes(fileContent))); 
     } 

 

Один из конструкторов DataContractJsonSerializer принимает тип класса в который будет происходить десериализация. Далее мы вызываем метод ReadObject, принимающий поток с данными Json. 

Если всё было сделано верно, то экземпляр класса Person будет создан и его свойства будут заполнены в соответствии с Json.

В дальнейшем, можно вывести эти данные, например так:

FNameLbl.Text = person.firstName; 
LNameLbl.Text = person.lastName; 
PhonesLbl.Text = string.Join(", ", person.phoneNumbers); 
StreetLbl.Text = person.address.streetAddress; 
CityLbl.Text = person.address.city; 
PostalLbl.Text = person.address.postalCode.ToString(); 

Всё должно работать, но есть один нюанс. Как вы наверно уже поняли, десериализация требует наличия в классе свойств, которые по имени совпадают с полями в Json. Так, например, в нашем Json все поля написаны с прописной буквы, и потому в классе Person тоже все свойства описаны идентично. Сами понимаете, что с точки зрения C# это недопустимо. Свойства класса должны начинаться с заглавной буквы.
 Дабы решить эту проблему и не привязывать десериализацию к именам свойств класса, необходимо использовать атрибуты свойств и классов.
 Наш класс с использованием атрибутов будет выглядеть так:
 

   [DataContract] 
   public class Person 
   { 
     [DataMember(Name = "firstName")] 
     public string FirstName { get; set; } 
     [DataMember(Name = "lastName")] 
     public string LastName { get; set; } 
     [DataMember(Name = "address")] 
     public Address PersonAddress { get; set; } 
     [DataMember(Name = "phoneNumbers")] 
     public string[] PersonPhones { get; set; } 
   } 
   [DataContract] 
   public class Address 
   { 
     [DataMember(Name = "streetAddress")] 
     public string StreetAddress { get; set; } 
     [DataMember(Name = "city")] 
     public string City { get; set; } 
     [DataMember(Name = "postalCode")] 
     public int Postal { get; set; } 
   } 

Теперь наш класс соответствует негласным правилам C#.