From 3fa089b85e8201c65de7a04ca72f616f693422ef Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 9 May 2019 11:58:55 -0400 Subject: [PATCH] feat: Added methods for serializing additional types, arrays and dictionaries to JSON --- .../Extensions/JsonReaderExtensions.cs | 70 ----- .../Extensions/JsonSerializerExtensions.cs | 295 ++++++++++++++++++ .../Extensions/JsonWriterExtensions.cs | 96 +++--- .../ICD.Common.Utils_SimplSharp.csproj | 1 + 4 files changed, 339 insertions(+), 123 deletions(-) create mode 100644 ICD.Common.Utils/Extensions/JsonSerializerExtensions.cs diff --git a/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs b/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs index 87892be..c854c8d 100644 --- a/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonReaderExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using ICD.Common.Properties; using ICD.Common.Utils.Json; using Newtonsoft.Json; @@ -215,73 +213,5 @@ namespace ICD.Common.Utils.Extensions string stringValue = extends.GetValueAsString(); return JsonUtils.ParseDateTime(stringValue); } - - /// - /// Deserializes an array of items from the reader's current value. - /// - /// - /// - /// - public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (reader == null) - throw new ArgumentNullException("reader"); - - return extends.DeserializeArray(reader, (s, r) => extends.Deserialize(reader)); - } - - /// - /// Deserializes an array of items from the reader's current value. - /// - /// - /// - /// - /// - public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader, - Func read) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (reader == null) - throw new ArgumentNullException("reader"); - - if (read == null) - throw new ArgumentNullException("read"); - - if (reader.TokenType == JsonToken.Null) - return Enumerable.Empty(); - - if (reader.TokenType != JsonToken.StartArray) - throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType)); - - return DeserializeArrayIterator(extends, reader, read); - } - - /// - /// Deserializes an array of items from the reader's current value. - /// - /// - /// - /// - /// - private static IEnumerable DeserializeArrayIterator(JsonSerializer serializer, JsonReader reader, - Func read) - { - // Step into the first value - reader.Read(); - - while (reader.TokenType != JsonToken.EndArray) - { - TItem output = read(serializer, reader); - yield return output; - - // Read out of the last value - reader.Read(); - } - } } } diff --git a/ICD.Common.Utils/Extensions/JsonSerializerExtensions.cs b/ICD.Common.Utils/Extensions/JsonSerializerExtensions.cs new file mode 100644 index 0000000..bd7ebaf --- /dev/null +++ b/ICD.Common.Utils/Extensions/JsonSerializerExtensions.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Newtonsoft.Json; + +namespace ICD.Common.Utils.Extensions +{ + public static class JsonSerializerExtensions + { + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader) + { + return extends.DeserializeArray(reader, (s, r) => extends.Deserialize(reader)); + } + + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + /// + public static IEnumerable DeserializeArray(this JsonSerializer extends, JsonReader reader, + Func read) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (read == null) + throw new ArgumentNullException("read"); + + if (reader.TokenType == JsonToken.Null) + return Enumerable.Empty(); + + if (reader.TokenType != JsonToken.StartArray) + throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType)); + + // ToArray to ensure everything gets read before moving onto the next token + return DeserializeArrayIterator(extends, reader, read).ToArray(); + } + + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + /// + private static IEnumerable DeserializeArrayIterator(JsonSerializer serializer, JsonReader reader, + Func read) + { + // Step into the first value + reader.Read(); + + while (reader.TokenType != JsonToken.EndArray) + { + TItem output = read(serializer, reader); + yield return output; + + // Step out of the value + reader.Read(); + } + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + public static IEnumerable> DeserializeDict(this JsonSerializer extends, + JsonReader reader) + { + return extends.DeserializeDict(reader, p => (TKey)Convert.ChangeType(p, typeof(TKey), CultureInfo.InvariantCulture)); + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + /// + public static IEnumerable> DeserializeDict(this JsonSerializer extends, + JsonReader reader, + Func getKey) + { + return extends.DeserializeDict(reader, getKey, (s, r) => extends.Deserialize(reader)); + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + /// + /// + public static IEnumerable> DeserializeDict(this JsonSerializer extends, + JsonReader reader, + Func getKey, + Func readValue) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (reader == null) + throw new ArgumentNullException("reader"); + + if (getKey == null) + throw new ArgumentNullException("getKey"); + + if (readValue == null) + throw new ArgumentNullException("readValue"); + + if (reader.TokenType == JsonToken.Null) + return Enumerable.Empty>(); + + if (reader.TokenType != JsonToken.StartObject) + throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType)); + + // ToArray to ensure everything gets read before moving onto the next token + return DeserializeDictIterator(extends, reader, getKey, readValue).ToArray(); + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + /// + /// + private static IEnumerable> DeserializeDictIterator( + JsonSerializer serializer, JsonReader reader, + Func getKey, + Func readValue) + { + // Step into the first property + reader.Read(); + + while (reader.TokenType != JsonToken.EndObject) + { + if (reader.TokenType != JsonToken.PropertyName) + throw new FormatException(); + + TKey key = getKey((string)reader.Value); + + // Step into the value + reader.Read(); + + TValue value = readValue(serializer, reader); + yield return new KeyValuePair(key, value); + + // Step out of the value + reader.Read(); + } + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items) + { + extends.SerializeArray(writer, items, (s, w, item) => s.Serialize(w, item)); + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + /// + public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items, + Action write) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + if (write == null) + throw new ArgumentNullException("write"); + + if (items == null) + { + writer.WriteNull(); + return; + } + + writer.WriteStartArray(); + { + foreach (TItem item in items) + write(extends, writer, item); + } + writer.WriteEndArray(); + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + /// + public static void SerializeDict(this JsonSerializer extends, JsonWriter writer, + IEnumerable> items) + { + extends.SerializeDict(writer, items, k => k.ToString()); + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + /// + /// + public static void SerializeDict(this JsonSerializer extends, JsonWriter writer, + IEnumerable> items, + Func getPropertyName) + { + extends.SerializeDict(writer, items, getPropertyName, (s, w, v) => s.Serialize(w, v)); + } + + /// + /// Serializes the given sequence of items to the writer. + /// + /// + /// + /// + /// + /// + /// + /// + public static void SerializeDict(this JsonSerializer extends, JsonWriter writer, + IEnumerable> items, + Func getPropertyName, + Action writeValue) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (writer == null) + throw new ArgumentNullException("writer"); + + if (getPropertyName == null) + throw new ArgumentNullException("getPropertyName"); + + if (writeValue == null) + throw new ArgumentNullException("writeValue"); + + if (items == null) + { + writer.WriteNull(); + return; + } + + writer.WriteStartObject(); + { + foreach (KeyValuePair kvp in items) + { + string propertyName = getPropertyName(kvp.Key); + writer.WritePropertyName(propertyName); + writeValue(extends, writer, kvp.Value); + } + } + writer.WriteEndObject(); + } + } +} \ No newline at end of file diff --git a/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs b/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs index cfb6671..2e5ff69 100644 --- a/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonWriterExtensions.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using ICD.Common.Properties; using Newtonsoft.Json; @@ -7,58 +6,6 @@ namespace ICD.Common.Utils.Extensions { public static class JsonWriterExtensions { - /// - /// Serializes the given sequence of items to the writer. - /// - /// - /// - /// - /// - public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (writer == null) - throw new ArgumentNullException("writer"); - - if (items == null) - throw new ArgumentNullException("items"); - - extends.SerializeArray(writer, items, (s, w, item) => s.Serialize(w, item)); - } - - /// - /// Serializes the given sequence of items to the writer. - /// - /// - /// - /// - /// - /// - public static void SerializeArray(this JsonSerializer extends, JsonWriter writer, IEnumerable items, - Action write) - { - if (extends == null) - throw new ArgumentNullException("extends"); - - if (writer == null) - throw new ArgumentNullException("writer"); - - if (items == null) - throw new ArgumentNullException("items"); - - if (write == null) - throw new ArgumentNullException("write"); - - writer.WriteStartArray(); - { - foreach (TItem item in items) - write(extends, writer, item); - } - writer.WriteEndArray(); - } - /// /// Writes the type value. /// @@ -80,6 +27,19 @@ namespace ICD.Common.Utils.Extensions extends.WriteValue(name); } + /// + /// Writes a Type value. + /// + /// + /// + public static void WriteValue(this JsonWriter extends, Type value) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + extends.WriteType(value); + } + /// /// Writes the property name and value to the writer. /// @@ -154,5 +114,35 @@ namespace ICD.Common.Utils.Extensions extends.WritePropertyName(propertyName); extends.WriteValue(value); } + + /// + /// Writes the property name and value to the writer. + /// + /// + /// + /// + public static void WriteProperty(this JsonWriter extends, string propertyName, Guid value) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + extends.WritePropertyName(propertyName); + extends.WriteValue(value); + } + + /// + /// Writes the property name and value to the writer. + /// + /// + /// + /// + public static void WriteProperty(this JsonWriter extends, string propertyName, Type value) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + extends.WritePropertyName(propertyName); + extends.WriteValue(value); + } } } diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index 80364f1..14fa4d7 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -105,6 +105,7 @@ +