From 2dc705d335deaccb0cd90f676561c312946120fa Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 4 Feb 2019 11:38:39 -0500 Subject: [PATCH] perf: Significantly reducing the size of JSON serialized types --- .../Extensions/JsonWriterExtensions.cs | 88 +++++++++++++++++-- 1 file changed, 83 insertions(+), 5 deletions(-) diff --git a/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs b/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs index 98b4fe8..acfb591 100644 --- a/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using ICD.Common.Properties; using Newtonsoft.Json; @@ -7,6 +8,16 @@ namespace ICD.Common.Utils.Extensions { public static class JsonWriterExtensions { + private static readonly Dictionary s_TypeToName; + + /// + /// Static constructor. + /// + static JsonWriterExtensions() + { + s_TypeToName = new Dictionary(); + } + /// /// Writes the type value. /// @@ -24,11 +35,7 @@ namespace ICD.Common.Utils.Extensions return; } - // Find the smallest possible name representation for the type that will still resolve - string name = Type.GetType(type.FullName) == null - ? type.AssemblyQualifiedName - : type.FullName; - + string name = GetTypeName(type); extends.WriteValue(name); } @@ -83,5 +90,76 @@ namespace ICD.Common.Utils.Extensions } writer.WriteEndArray(); } + + /// + /// Gets the string representation foe the given type. + /// + /// + /// + private static string GetTypeName(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + + string name; + if (!s_TypeToName.TryGetValue(type, out name)) + { + name = RemoveAssemblyDetails(type.AssemblyQualifiedName); + s_TypeToName.Add(type, name); + } + + return name; + } + + /// + /// Taken from Newtonsoft.Json.Utilities.ReflectionUtils + /// Removes the assembly details from a type assembly qualified name. + /// + /// + /// + private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) + { + StringBuilder builder = new StringBuilder(); + + // loop through the type name and filter out qualified assembly details from nested type names + bool writingAssemblyName = false; + bool skippingAssemblyDetails = false; + for (int i = 0; i < fullyQualifiedTypeName.Length; i++) + { + char current = fullyQualifiedTypeName[i]; + switch (current) + { + case '[': + writingAssemblyName = false; + skippingAssemblyDetails = false; + builder.Append(current); + break; + case ']': + writingAssemblyName = false; + skippingAssemblyDetails = false; + builder.Append(current); + break; + case ',': + if (!writingAssemblyName) + { + writingAssemblyName = true; + builder.Append(current); + } + else + { + skippingAssemblyDetails = true; + } + break; + default: + if (!skippingAssemblyDetails) + { + builder.Append(current); + } + break; + } + } + + return builder.ToString(); + } } }