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!