Windows Phone Tips & Tricks. Cómo serializar un objeto a un fichero Json en SkyDrive y deserializarlo

[Nota: Este artículo pertenece a la serie de Windows Phone Tips & Tricks de MSDN España]

Hola,

En mi app de Windows Phone 8 ya serializo objetos a ficheros Json y los deserializo en el almacenamiento local del dispositivo sin problemas. El siguiente paso ha sido añadirle a la app la opción de serializar los objetos a ficheros en SkyDrive, para poder hacer así una copia de seguridad de los mismos.

Para acceder a SkyDrive uso el LiveSDK, cuyo paquete NuGet (en su versión 5.3 a la hora de escribir esto) he referenciado en mi proyecto (nota: aquí tienes un ejemplo de cómo añadir paquetes NuGet a tu proyecto). También he dado de alta mi app como Aplicación de cliente móvil en el Centro para desarrolladores de Live Connect. De ahí saco el clientId que uso después en mi código.

La clase que utilizo para serializar/deserializar los objetos es como la siguiente:

using Microsoft.Live;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;

namespace MyApp.Services
{
    public class SkyDriveService
    {
        // Constructor
        public SkyDriveService()
        {

        }

        // Deserializa un objeto de un fichero
        public async Task<T> LoadAsync<T>(string clientId, List<string> folderNames, string fileName)
        {
            // Usa una sesión de sólo lectura ya existente
            LiveAuthClient authClient = new LiveAuthClient(clientId);
            LiveLoginResult initializeResult = await authClient.InitializeAsync(new string[] { "wl.offline_access", "wl.skydrive" });
            if (initializeResult.Status != LiveConnectSessionStatus.Connected)
            {
                // Si no la hay, haz logon y crea una nueva sesión
                LiveLoginResult loginResult = await authClient.LoginAsync(new string[] { "wl.offline_access", "wl.skydrive" });
                if (loginResult.Status != LiveConnectSessionStatus.Connected) { return default(T); }
            }

            // Conectate a SkyDrive con esa sesión
            LiveConnectClient connectClient = new LiveConnectClient(authClient.Session);

            // Empieza en la carpeta raiz del SkyDrive del usuario
            string folderId = "me/skydrive";

            // Busca la carpeta en la que debería de estar el fichero
            foreach (string folderName in folderNames)
            {
                // Obtén las subcarpetas de la carpeta anterior
                LiveOperationResult getFoldersResult = await connectClient.GetAsync(folderId + "/files?filter=folders");
                dynamic foldersResult = getFoldersResult.Result;
                List<dynamic> folders = foldersResult.data;

                // Encuentra la carpeta actual entre esas subcarpetas
                dynamic currentFolder = folders.Where(folder => folder.name == folderName).SingleOrDefault();
                if (currentFolder == null)
                {
                    // Si la carpeta actual no existe, hemos terminado
                    return default(T);
                }

                // Quédate con la ruta en SkyDrive de esta carpeta y pasa a la siguiente de la lista
                folderId = currentFolder.id;
            }

            // Obtén los ficheros de la carpeta elegida
            LiveOperationResult getFilesResult = await connectClient.GetAsync(folderId + "/files");
            dynamic filesResult = getFilesResult.Result;
            List<dynamic> files = filesResult.data;

            // Encuentra el fichero que buscamos en esa carpeta
            dynamic currentFile = files.Where(file => file.name == fileName).SingleOrDefault();
            if (currentFile == null)
            {
                // Si el fichero no existe, hemos terminado
                return default(T);
            }

            // Si lo has encontrado, descárgalo
            string fileId = currentFile.id;
            LiveDownloadOperationResult downloadResult = await connectClient.DownloadAsync(fileId + "/content");
            Stream stream = downloadResult.Stream;

            // Deserializa el contenido del fichero
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T));
            T data = (T)json.ReadObject(stream);
            return data;
        }

        // Serializa un objeto a fichero
        public async Task SaveAsync<T>(string clientId, List<string> folderNames, string fileName, T data)
        {
            // Usa una sesión de lectura/escritura ya existente
            LiveAuthClient authClient = new LiveAuthClient(clientId);
            LiveLoginResult initializeResult = await authClient.InitializeAsync(new string[] { "wl.offline_access", "wl.skydrive_update" });
            if (initializeResult.Status != LiveConnectSessionStatus.Connected)
            {
                // Si no la hay, haz logon y crea una nueva sesión
                LiveLoginResult loginResult = await authClient.LoginAsync(new string[] { "wl.offline_access", "wl.skydrive_update" });
                if (loginResult.Status != LiveConnectSessionStatus.Connected) { return; }
            }

            // Conectate a SkyDrive con esa sesión
            LiveConnectClient connectClient = new LiveConnectClient(authClient.Session);

            // Empieza en la carpeta raiz del SkyDrive del usuario
            string folderId = "me/skydrive";

            // Busca la carpeta en la que acabaremos creando el fichero
            foreach (string folderName in folderNames)
            {
                // Obtén las subcarpetas de la carpeta anterior
                LiveOperationResult getResult = await connectClient.GetAsync(folderId + "/files?filter=folders");
                dynamic result = getResult.Result;
                List<dynamic> folders = result.data;

                // Encuentra la carpeta actual entre esas subcarpetas
                dynamic currentFolder = folders.Where(folder => folder.name == folderName).SingleOrDefault();
                if (currentFolder == null)
                {
                    // Si la carpeta actual no existe, créala
                    Dictionary<string, object> skyDriveFolderData = new Dictionary<string, object>();
                    skyDriveFolderData.Add("name", folderName);
                    LiveOperationResult postResult = await connectClient.PostAsync(folderId, skyDriveFolderData);
                    currentFolder = postResult.Result;
                }

                // Quédate con la ruta en SkyDrive de esta carpeta y pasa a la siguiente de la lista
                folderId = currentFolder.id;
            }

            // Serializa el objeto al fichero en la carpeta elegida
            MemoryStream stream = new MemoryStream();
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T));
            json.WriteObject(stream, data);
            stream.Seek(0, SeekOrigin.Begin);
            LiveOperationResult uploadResult = await connectClient.UploadAsync(folderId, fileName, stream, OverwriteOption.Overwrite);
        }
    }
}

Si quiero serializar un objeto con esta clase podría hacerlo con un código similar a este:

MyClass myObject;
...

List<string> folderNames = new List<string>();
folderNames.Add("AppData");
folderNames.Add("Nombre de mi app");

await SkyDriveService.SaveAsync<MyClass>("Mi clientId de SkyDrive", folderNames, "Nombre de mi fichero", myObject);

Y para deserializarlo podría usar un código similar a este:

List<string> folderNames = new List<string>();
folderNames.Add("AppData");
folderNames.Add("Nombre de mi app");

MyClass myObject = await SkyDriveService.LoadAsync<MyClass>("Mi clientId de SkyDrive", folderNames, "Nombre de mi fichero");

Nota: si en la clase del objeto que estás serializando hay alguna propiedad que no quieras o puedas serializar, utiliza el atributo [IgnoreDataMember] para que no sea tenida en cuenta.

Nota: puedes encontrar más información sobre la Live API aquí.

Espero que te sea de utilidad.

Un saludo,

Alejandro Campos Magencio (@alejacma)

PD: Mantente informado de todas las novedades de Microsoft para los desarrolladores españoles a través del Twitter de MSDN, el Facebook de MSDN, el Blog de MSDN y la Newsletter MSDN Flash.

About these ads

3 pensamientos en “Windows Phone Tips & Tricks. Cómo serializar un objeto a un fichero Json en SkyDrive y deserializarlo

  1. Pingback: Tips & Tricks de desarrollo para Windows Phone - MSDN España - Site Home - MSDN Blogs

  2. Pingback: Windows Phone Tips & Tricks. Cómo actualizar el Live Tile principal de mi app | ¡Desarrolladores, desarrolladores, desarrolladores!

  3. Pingback: Sácale mayor partido a tus apps en Windows Phone - MSDN España - Site Home - MSDN Blogs

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s