Sdílet prostřednictvím


Get With the Times - Get Rid Of the Bloated XML Data Format And Switch To JSON

  1. One of my blog readers told me it was 2014

  2. He laughed at the fact that I was still using XML

  3. So within 30 minutes I was writing JSON to disk, instead of XML

  4. It was incredibly easy to do

  5. It is much easier than you might expect

  6. I eliminated an un-needed class and persisted my data into a smaller payload

INSTALL THE NUGET PACKAGE FOR JSON.NET

  1. In Visual Studio use the Tools menu

    image001

    Figure 1: Adding a NuGet Package - Json.Net

THE OLD XML-BASED APPROACH

  1. This is the code that I eliminated to Json-ify it

    • Line 15 and 50 were changed to make it Json
    • Lines 71 to 104 were eliminated
Old, XML Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Old Code using XML // // private static async Task SaveToDiskFolders(ObservableCollection<FoldersItem> collection, string filename) {     // Creat a save-able object list     List<FoldersItemDisk> dataToSave = new List<FoldersItemDisk>();     foreach (FoldersItem item in collection)     {         dataToSave.Add(new FoldersItemDisk { FolderName = item.FolderName });     }     // Make xml out of it          // Save to disk part 1     StorageFolder storageFolder = ApplicationData.Current.LocalFolder;     StorageFile storageFile =             await storageFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);     // Save to disk part 2     using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))     {         using (DataWriter dataWriter = new DataWriter(stream))         {             dataWriter.WriteString(localData);             await dataWriter.StoreAsync();         }     } } private async Task ReadFromFileFolders(ObservableCollection<FoldersItem> collection, ResetCollectionWithSource myfunc, string filename) {     try     {         StorageFolder storageFolder = ApplicationData.Current.LocalFolder;         StorageFile storageFile =                 await storageFolder.GetFileAsync(filename);         using (IRandomAccessStreamWithContentType readStream = await storageFile.OpenReadAsync())         using (DataReader reader = new DataReader(readStream))         {             ulong streamSize = readStream.Size;             UInt32 totalBytesRead = await reader.LoadAsync((UInt32)streamSize);             string s = reader.ReadString(totalBytesRead);                         collection.Clear();             foreach (FoldersItemDisk item in localData)             {                 collection.Add(new FoldersItem {                         FolderName = item.FolderName,                         Folder = await StorageFolder.GetFolderFromPathAsync(item.FolderName)                 });             }             myfunc();                     }     }     catch (FileNotFoundException)     {     } } internal static class ObjectSerializer<T> {         // Serialize to xml         public static string ToXml(T value)         {             XmlSerializer serializer = new XmlSerializer(typeof(T));             StringBuilder stringBuilder = new StringBuilder();             XmlWriterSettings settings = new XmlWriterSettings()             {                 Indent = true,                 OmitXmlDeclaration = true,             };             using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, settings))             {                 serializer.Serialize(xmlWriter, value);             }             return stringBuilder.ToString();         }         // Deserialize from xml         public static T FromXml(string xml)         {             XmlSerializer serializer = new XmlSerializer(typeof(T));             T value;             using (StringReader stringReader = new StringReader(xml))             {                 object deserialized = serializer.Deserialize(stringReader);                 value = (T)deserialized;             }             return value;         } }

THE NEW, MODERN, JSON-BASED APPROACH

  1. After adding the Json.NET package, I just changed the code to look like this

    • Lines 15 to 18 are new
    • Lines 54 to 57 are new
New, Json Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // New Code using JSON // // private static async Task SaveToDiskFolders(ObservableCollection<FoldersItem> collection, string filename) {     // Creat a save-able object list     List<FoldersItemDisk> dataToSave = new List<FoldersItemDisk>();     foreach (FoldersItem item in collection)     {         dataToSave.Add(new FoldersItemDisk { FolderName = item.FolderName });     }     // New JSON approach     string localData = JsonConvert.SerializeObject(dataToSave, new JsonSerializerSettings     {         Formatting = Formatting.Indented     });     // Save to disk part 1     StorageFolder storageFolder = ApplicationData.Current.LocalFolder;     StorageFile storageFile =             await storageFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);     // Save to disk part 2     using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))     {         using (DataWriter dataWriter = new DataWriter(stream))         {             dataWriter.WriteString(localData);             await dataWriter.StoreAsync();         }     } } private async Task ReadFromFileFolders(ObservableCollection<FoldersItem> collection, ResetCollectionWithSource myfunc, string filename) {     try     {         StorageFolder storageFolder = ApplicationData.Current.LocalFolder;         StorageFile storageFile =                 await storageFolder.GetFileAsync(filename);         using (IRandomAccessStreamWithContentType readStream = await storageFile.OpenReadAsync())         using (DataReader reader = new DataReader(readStream))         {             ulong streamSize = readStream.Size;             UInt32 totalBytesRead = await reader.LoadAsync((UInt32)streamSize);             string s = reader.ReadString(totalBytesRead);             List<FoldersItemDisk> localData = JsonConvert.DeserializeObject<List<FoldersItemDisk>>(s, new JsonSerializerSettings             {                 Formatting = Formatting.Indented             });             collection.Clear();             foreach (FoldersItemDisk item in localData)             {                 collection.Add(new FoldersItem {                         FolderName = item.FolderName,                         Folder = await StorageFolder.GetFolderFromPathAsync(item.FolderName)                 });             }             myfunc();                     }     }     catch (FileNotFoundException)     {     } }

Conclusion

Now is the time to go to your code and bring it into 2014.

Comments

  • Anonymous
    July 16, 2014
    wow. that was a fast change! awesome :)

  • Anonymous
    July 16, 2014
    All this json thing is nice and all, but good luck if you reuse the same object in multiple places of your hiearchy: only XML and DataContract(IsReference=true) will do the trick correctly. But Json is perfect for simpler things.

  • Anonymous
    July 17, 2014
    Now we need integration of JSON with MsSQL Engine as a new type ;-).

  • Anonymous
    July 17, 2014
    @tec - this can be done with JSON, too.