[VISUAL STUDIO] Pegar XML o JSON como Clases

En este articulo vamos a usar una utilidad incluida en Visual Studio 2012 la cual permite crear la estructura de clases necesarias para convertir cadena de texto en formato XML o JSON. Esta necesidad nos surgió ha raíz de realizar un SDK .NET para LinkedIn. Concretamente cuando se hace una petición a

https://api.linkedin.com/v1/people/~

la respuesta estandar de la plataforma linkedin es un XML con el formato:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
		<first-name>Sergio</first-name>
		<last-name>Montes Padilla</last-name>
		<headline>Analista programador .NET</headline>
		<site-standard-profile-request>
			<url>http://www.linkedin.com/profile/view?id=44631052&amp;authType=name&amp;authToken=66hk&amp;trk=api*a306026*s313536*</url>
		</site-standard-profile-request>
</person>


Ahora vamos a usar VS2012 para crear las clases necesarias para  transformar este XML a un objeto .NET. Lo primero copiamos [CTRL+C] esta cadena y seleccionamos la opción de menú “Editar->Pegado Especial->Pegar XML como clases”

Opcion Menu

Para nuestro XML de ejemplo, esta utilidad nos creará las siguiente estructura de clases

    /// <comentarios/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class person
    {

        private string firstnameField;

        private string lastnameField;

        private string headlineField;

        private personSitestandardprofilerequest sitestandardprofilerequestField;

        /// <comentarios/>
        [System.Xml.Serialization.XmlElementAttribute("first-name")]
        public string firstname
        {
            get
            {
                return this.firstnameField;
            }
            set
            {
                this.firstnameField = value;
            }
        }

        /// <comentarios/>
        [System.Xml.Serialization.XmlElementAttribute("last-name")]
        public string lastname
        {
            get
            {
                return this.lastnameField;
            }
            set
            {
                this.lastnameField = value;
            }
        }

        /// <comentarios/>
        public string headline
        {
            get
            {
                return this.headlineField;
            }
            set
            {
                this.headlineField = value;
            }
        }

        /// <comentarios/>
        [System.Xml.Serialization.XmlElementAttribute("site-standard-profile-request")]
        public personSitestandardprofilerequest sitestandardprofilerequest
        {
            get
            {
                return this.sitestandardprofilerequestField;
            }
            set
            {
                this.sitestandardprofilerequestField = value;
            }
        }
    }

    /// <comentarios/>
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class personSitestandardprofilerequest
    {

        private string urlField;

        /// <comentarios/>
        public string url
        {
            get
            {
                return this.urlField;
            }
            set
            {
                this.urlField = value;
            }
        }
    }

ahora vamos a ver como con unas pocas lineas de código convertimos nuestra cadena XML a un objeto .NET

        private void btnDeserializarXML_Click(object sender, RoutedEventArgs e)
        {
            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(person));
            System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(txtXml.Text));
            person datosPerfil = ser.Deserialize(ms) as person;
            if (datosPerfil != null)
            {
                txtObjetoXML.Text = string.Format("Nombre:{0}\nApellidos{1}\nProfesion:{2}\nURL Perfil:{3}", datosPerfil.firstname, datosPerfil.lastname, datosPerfil.headline, datosPerfil.sitestandardprofilerequest.url);
            }
        }

El código anterior tan solo crea una instancia XmlSerializer e invoca al método Deserialize, tomando como parámetro un objeto MemoryStream, el cual hemos inicializado con la cadena xml.

Este proceso también se puede realizar a la inversa, es decir, en base a un objeto .NET, crear la cadena XML (Serializar).

private void btnSerializarXML_Click(object sender, RoutedEventArgs e)
{
if (datosPerfil == null) datosPerfil = new person();
datosPerfil.firstname += "-modificado";

System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(person));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ser.Serialize(ms, datosPerfil);
if (ms != null)
{
ms.Flush();
ms.Position = 0;
System.IO.StreamReader sr = new System.IO.StreamReader(ms);
txtXml.Text = sr.ReadToEnd();
}
}

En este ejemplo, hemos utilizado el método Serialize de la clase XmlSerializer para convertir nuestra instancia a un MemoryStream, el cual posteriormente es transformado a un string usando una instancia de StreamReader.

En el caso de JSON, el proceso es muy similar pero en lugar de usar XmlSerializer, vamos a usar la librería Newtonsoft.Json (accesible vía Nuget). Dado la siguiente cadena JSON

{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"] },
"GlossSee": "markup"
}
}
}
}
}

Si ahora copiamos esta cadena JSON, y utilizamos la opción “Pegar JSON como clases“, Visual Studio crea la siguiente estructura de clases:

public class Rootobject
{
public Glossary glossary { get; set; }
}

public class Glossary
{
public string title { get; set; }
public Glossdiv GlossDiv { get; set; }
}

public class Glossdiv
{
public string title { get; set; }
public Glosslist GlossList { get; set; }
}

public class Glosslist
{
public Glossentry GlossEntry { get; set; }
}

public class Glossentry
{
public string ID { get; set; }
public string SortAs { get; set; }
public string GlossTerm { get; set; }
public string Acronym { get; set; }
public string Abbrev { get; set; }
public Glossdef GlossDef { get; set; }
public string GlossSee { get; set; }
}

public class Glossdef
{
public string para { get; set; }
public string[] GlossSeeAlso { get; set; }
}

La deserializacion la vamos a realizar usando la JsonConver.DeserializeObject<T>

        private void btnDeserializarJSON_Click(object sender, RoutedEventArgs e)
        {
            objJSON = Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(txtJSON.Text);
            if (objJSON != null)
            {
                StringBuilder cadResultado=new StringBuilder();
                cadResultado.AppendFormat("title:{0}\n",objJSON.glossary.title);
                cadResultado.AppendFormat("Abbrev:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.Abbrev);
                cadResultado.AppendFormat("Acronym:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.Acronym);
                cadResultado.AppendFormat("GlossDef:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.GlossDef);
                cadResultado.AppendFormat("GlossSee:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.GlossSee);
                cadResultado.AppendFormat("GlossTerm:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.GlossTerm);
                cadResultado.AppendFormat("ID:{0}\n",objJSON.glossary.GlossDiv.GlossList.GlossEntry.ID);
                txtObjetoJSON.Text = cadResultado.ToString();
            }

        }

mientras que la serializacion la podemos realizar usando JsonConver.SerializeObject

        private void btnSerializarJSON_Click(object sender, RoutedEventArgs e)
        {
            objJSON.glossary.title = "Modificado-Modificado-Modificado-Modificado";
            txtJSON.Text = Newtonsoft.Json.JsonConvert.SerializeObject(objJSON);
        }

En el siguiente enlace, puedes descargar un proyecto con una demostración: http://sdrv.ms/1460NlA