Back-End

5 abr, 2018

Serialização em C#

Publicidade

Introdução

Antes de irmos diretamente para o código, vamos entender brevemente o que é serialização e deserialização.

Serializar é o processo de transformar um objeto que você possui em um stream de bytes ou de texto. Deserializar, por sua vez, é exatamente o oposto. É converter um stream de bytes ou de texto em um objeto novamente.

Para nos ajudar nesse processo, o .NET Framework oferece algumas classes que podem ser encontradas nos namespaces System.Runtime.Serialization e System.Xml.Serialization, além de nos oferecer por padrão, três mecanismos serialização/deserialização:

  • BinaryFormatter
  • XmlSerializer
  • DataContractSerializer

Logo mais nesse artigo veremos como utilizar cada um desses mecanismos na prática, portanto, usaremos a classe Person, que se encontra logo abaixo como base para nossos exemplos.

public class Person 

{ 
public int Id { get; set; } 
public string FirstName { get; set; } 
public string LastName { get; set; } 
public string Email { get; set; } 
public int Age; 
 
public Person() { } 
 
public Person(int id, string firstName, string lastName, string email, int age) 
{ 
Id = id; 
FirstName = firstName; 
LastName = lastName; 
Email = email; 
Age = age; 
} 
}

Binary serialization

A serialização binária, como o próprio nome já sugere, serializa um objeto ou dado para o formato binário. Esse tipo de serialização armazena não somente os dados, mas também o tipo de objeto que está sendo serializado.

Para utilizarmos esse tipo de serialização, devemos marcar nossa classe como o atributo [Serializable], sendo que todos os campos podem ser serializados, inclusive os marcados como private, portanto, caso queiramos impedir que algum campo da nossa classe não seja serializado, devemos marca-la com o atributo [NonSerialized]. Também é importante ressaltarmos que propriedades serão sempre serializadas e que nenhum construtor é executado nesse tipo de serialização.

Outra característica importante é que esse tipo de serialização também é “mais rigorosa” que as demais. Se o serializador binário não achar algum campo, por exemplo, ele retornará uma Exception. No caso de uma atualização de versão, por exemplo, você pode adicionar o [OptionalFieldAttribute] no novo campo adicionado para que a serialização binária entenda que esse campo não existia antes, por exemplo.

//Criamos uma nova pessoa para serializarmos 

var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe BinarryFormatter 
var binaryFormatter = new BinaryFormatter(); 

//Criamos um arquivo .bin que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("iMasters.bin", FileMode.Create)) 
{ 
    binaryFormatter.Serialize(fileStream, person); 
} 
Console.WriteLine("Serialização Concluida"); 
 
//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("iMasters.bin", FileMode.Open)) 
{ 
    var p = (Person)binaryFormatter.Deserialize(fileStream); 
} 
Console.WriteLine("Deserialização Concluida");

XML serialization

Ao contrário do modelo de serialização anterior, o XML é um tipo de dado legível também para seres humanos, e é fracamente acoplado, ou seja, se você adicionar propriedades ou campos ao seu objeto a ser serializado, ele não notará.

Assim como na serialização binária, para serializarmos, precisamos marcar o objeto com o atributo [Serializable], entretanto, aqui somente os campos e/ou propriedades públicas são serializadas. Caso queiramos que um campo e/ou propriedade não seja serializado, devemos marca-lo com o atributo [XmlIgnore].

Vale lembrar que propriedades também podem ser ignoradas e não somente campos, além de que, na serialização XML se faz necessário ter um construtor vazio na classe, diferentemente do modelo de serialização anterior.

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe XmlSerializer, e "dizemos" a ele que tipo de objeto vamos serializar. 
var xml = new XmlSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("iMasters.xml", FileMode.Create)) 
{ 
    xml.Serialize(fileStream, person); 
} 
Console.WriteLine("Serialização Concluida"); 

//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("iMasters.xml", FileMode.Open)) 
{ 
    var p = (Person)xml.Deserialize(fileStream); 
} 
Console.WriteLine("Deserialização Concluida");

Data Contract

O Data Contract Serializer é utilizado pelo WCF para serializar seus objetos tanto em XML quanto em JSON. Esse tipo de serialização é feita pelas classes DataContractSerializer para XML e DataContractJsonSerializer para JSON (discutido mais adiante).

Nesse modelo eu preciso marcar meu objeto a ser serializado com o atributo [DataContract], além de que nesse modelo, ao contrario dos outros, eu preciso marcar todos os membros que eu desejo serializar explicitamente com o atributo [DataMember]. Caso eu deseje ignorar algum membro, devemos marca-lo com o atributo [IgnoreDataMember] ou se preferir, apenas deixa-lo sem a marcação do atributo [DataMember]. Outra característica importante é que nesse modelo, campos privados também podem ser serializados.

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe DataContractSerializer, para serializarmos em XML e "dizemos" a ele que tipo de objeto vamos serializar. 
var dataContract = new DataContractSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("iMasters.xml", FileMode.Create)) 
{ 
    dataContract.WriteObject(fileStream, person); 
} 
Console.WriteLine("Serialização Concluida"); 
 
//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("iMasters.xml", FileMode.Open)) 
{ 
    var p = (Person)dataContract.ReadObject(fileStream); 
} 
Console.WriteLine("Deserialização Concluida");

JSON serialization

Utiliza-se também o Data Contract Serializer e suas respectivas características para que a serialização seja efetuada. Porém, com uma única alteração: ao invés de eu utilizar a classe DataContractSerializer eu utilizo a classe DataContractJsonSerializer para que possamos serializar em JSON.

//Criamos uma nova pessoa para serializarmos 
var person = new Person(1, "João", "da Silva", "joao.silva@xpto.com", 50); 

//Instanciamos a classe DataContractJsonSerializer, para serializarmos em JSON e "dizemos" a ele que tipo de objeto vamos serializar. 
var dataContract = new DataContractJsonSerializer(typeof(Person)); 

//Criamos um arquivo .xml que receberá os dados serializados do objeto person 
using (var fileStream = new FileStream("iMasters.json", FileMode.Create)) 
{ 
    dataContract.WriteObject(fileStream, person); 
} 
Console.WriteLine("Serialização Concluida"); 

//Abrimos o arquivo serializado anteriormente para podermos deserializa-lo. 
using (var fileStream = new FileStream("iMasters.json", FileMode.Open)) 
{ 
    var p = (Person)dataContract.ReadObject(fileStream); 
} 
Console.WriteLine("Deserialização Concluida");

Bom, pessoal, a ideia desse artigo era mostrar as particularidades e exemplos de como utilizar cada um dos modelos de serialização utilizando o C#.

Espero que tenham gostado do artigo e até a próximo!