From 43d2fab203cf6993d021b6b5e372dbf440a7d6f5 Mon Sep 17 00:00:00 2001 From: TylerBrinkley Date: Thu, 8 Sep 2016 11:24:45 -0500 Subject: [PATCH] Added a generic JsonConverter and changed the base types of some of the existing converters to this new generic JsonConverter where relevant. --- .../Converters/BsonObjectIdConverter.cs | 25 ++----- .../Converters/DataSetConverter.cs | 22 ++---- .../Converters/DataTableConverter.cs | 26 ++----- .../Converters/RegexConverter.cs | 29 +++----- .../Converters/VersionConverter.cs | 28 ++------ Src/Newtonsoft.Json/JsonConverter.cs | 72 +++++++++++++++++++ 6 files changed, 103 insertions(+), 99 deletions(-) diff --git a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs index c0a30ba3..e22a11d2 100644 --- a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs @@ -33,7 +33,7 @@ namespace Newtonsoft.Json.Converters /// /// Converts a to and from JSON and BSON. /// - public class BsonObjectIdConverter : JsonConverter + public class BsonObjectIdConverter : JsonConverter { /// /// Writes the JSON representation of the object. @@ -41,18 +41,16 @@ namespace Newtonsoft.Json.Converters /// The to write to. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, BsonObjectId value, JsonSerializer serializer) { - BsonObjectId objectId = (BsonObjectId)value; - BsonWriter bsonWriter = writer as BsonWriter; if (bsonWriter != null) { - bsonWriter.WriteObjectId(objectId.Value); + bsonWriter.WriteObjectId(value.Value); } else { - writer.WriteValue(objectId.Value); + writer.WriteValue(value.Value); } } @@ -61,10 +59,11 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The existing value has a value. /// The existing value of object being read. /// The calling serializer. /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override BsonObjectId ReadJson(JsonReader reader, Type objectType, bool existingHasValue, BsonObjectId existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.Bytes) { @@ -75,17 +74,5 @@ namespace Newtonsoft.Json.Converters return new BsonObjectId(value); } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(BsonObjectId)); - } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs index 5c86e827..395c4e45 100644 --- a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs @@ -33,7 +33,7 @@ namespace Newtonsoft.Json.Converters /// /// Converts a to and from JSON. /// - public class DataSetConverter : JsonConverter + public class DataSetConverter : JsonConverter { /// /// Writes the JSON representation of the object. @@ -41,16 +41,15 @@ namespace Newtonsoft.Json.Converters /// The to write to. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, DataSet value, JsonSerializer serializer) { - DataSet dataSet = (DataSet)value; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; DataTableConverter converter = new DataTableConverter(); writer.WriteStartObject(); - foreach (DataTable table in dataSet.Tables) + foreach (DataTable table in value.Tables) { writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(table.TableName) : table.TableName); @@ -65,10 +64,11 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The existing value has a value. /// The existing value of object being read. /// The calling serializer. /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override DataSet ReadJson(JsonReader reader, Type objectType, bool existingHasValue, DataSet existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -101,18 +101,6 @@ namespace Newtonsoft.Json.Converters return ds; } - - /// - /// Determines whether this instance can convert the specified value type. - /// - /// Type of the value. - /// - /// true if this instance can convert the specified value type; otherwise, false. - /// - public override bool CanConvert(Type valueType) - { - return typeof(DataSet).IsAssignableFrom(valueType); - } } } diff --git a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs index fcac67bc..a1616b6a 100644 --- a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -36,7 +36,7 @@ namespace Newtonsoft.Json.Converters /// /// Converts a to and from JSON. /// - public class DataTableConverter : JsonConverter + public class DataTableConverter : JsonConverter { /// /// Writes the JSON representation of the object. @@ -44,14 +44,13 @@ namespace Newtonsoft.Json.Converters /// The to write to. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, DataTable value, JsonSerializer serializer) { - DataTable table = (DataTable)value; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartArray(); - foreach (DataRow row in table.Rows) + foreach (DataRow row in value.Rows) { writer.WriteStartObject(); foreach (DataColumn column in row.Table.Columns) @@ -77,19 +76,20 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The existing value has a value. /// The existing value of object being read. /// The calling serializer. /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override DataTable ReadJson(JsonReader reader, Type objectType, bool existingHasValue, DataTable existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } - DataTable dt = existingValue as DataTable; + DataTable dt = existingValue; - if (dt == null) + if (!existingHasValue) { // handle typed datasets dt = (objectType == typeof(DataTable)) @@ -230,18 +230,6 @@ namespace Newtonsoft.Json.Converters throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); } } - - /// - /// Determines whether this instance can convert the specified value type. - /// - /// Type of the value. - /// - /// true if this instance can convert the specified value type; otherwise, false. - /// - public override bool CanConvert(Type valueType) - { - return typeof(DataTable).IsAssignableFrom(valueType); - } } } diff --git a/Src/Newtonsoft.Json/Converters/RegexConverter.cs b/Src/Newtonsoft.Json/Converters/RegexConverter.cs index bfbea4c2..a2f8f4ae 100644 --- a/Src/Newtonsoft.Json/Converters/RegexConverter.cs +++ b/Src/Newtonsoft.Json/Converters/RegexConverter.cs @@ -34,7 +34,7 @@ namespace Newtonsoft.Json.Converters /// /// Converts a to and from JSON and BSON. /// - public class RegexConverter : JsonConverter + public class RegexConverter : JsonConverter { private const string PatternName = "Pattern"; private const string OptionsName = "Options"; @@ -45,18 +45,16 @@ namespace Newtonsoft.Json.Converters /// The to write to. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, Regex value, JsonSerializer serializer) { - Regex regex = (Regex)value; - BsonWriter bsonWriter = writer as BsonWriter; if (bsonWriter != null) { - WriteBson(bsonWriter, regex); + WriteBson(bsonWriter, value); } else { - WriteJson(writer, regex, serializer); + WriteJsonInternal(writer, value, serializer); } } @@ -101,7 +99,7 @@ namespace Newtonsoft.Json.Converters writer.WriteRegex(regex.ToString(), options); } - private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer) + private void WriteJsonInternal(JsonWriter writer, Regex regex, JsonSerializer serializer) { DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; @@ -118,10 +116,11 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The existing value has a value. /// The existing value of object being read. /// The calling serializer. /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override Regex ReadJson(JsonReader reader, Type objectType, bool existingHasValue, Regex existingValue, JsonSerializer serializer) { switch (reader.TokenType) { @@ -136,7 +135,7 @@ namespace Newtonsoft.Json.Converters throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex."); } - private object ReadRegexString(JsonReader reader) + private Regex ReadRegexString(JsonReader reader) { string regexText = (string)reader.Value; int patternOptionDelimiterIndex = regexText.LastIndexOf('/'); @@ -211,17 +210,5 @@ namespace Newtonsoft.Json.Converters throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex."); } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(Regex)); - } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/VersionConverter.cs b/Src/Newtonsoft.Json/Converters/VersionConverter.cs index 3f512e44..51459c1d 100644 --- a/Src/Newtonsoft.Json/Converters/VersionConverter.cs +++ b/Src/Newtonsoft.Json/Converters/VersionConverter.cs @@ -32,7 +32,7 @@ namespace Newtonsoft.Json.Converters /// /// Converts a to and from a string (e.g. "1.2.3.4"). /// - public class VersionConverter : JsonConverter + public class VersionConverter : JsonConverter { /// /// Writes the JSON representation of the object. @@ -40,20 +40,13 @@ namespace Newtonsoft.Json.Converters /// The to write to. /// The value. /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); } - else if (value is Version) - { - writer.WriteValue(value.ToString()); - } - else - { - throw new JsonSerializationException("Expected Version object value"); - } + writer.WriteValue(value.ToString()); } /// @@ -61,10 +54,11 @@ namespace Newtonsoft.Json.Converters /// /// The to read from. /// Type of the object. + /// The existing value has a value. /// The existing property value of the JSON that is being converted. /// The calling serializer. /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override Version ReadJson(JsonReader reader, Type objectType, bool existingHasValue, Version existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -90,17 +84,5 @@ namespace Newtonsoft.Json.Converters } } } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override bool CanConvert(Type objectType) - { - return objectType == typeof(Version); - } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonConverter.cs b/Src/Newtonsoft.Json/JsonConverter.cs index a973d38b..64ea19fb 100644 --- a/Src/Newtonsoft.Json/JsonConverter.cs +++ b/Src/Newtonsoft.Json/JsonConverter.cs @@ -28,6 +28,7 @@ using System.Collections.Generic; using System.Text; using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Schema; +using System.Globalization; namespace Newtonsoft.Json { @@ -96,4 +97,75 @@ namespace Newtonsoft.Json get { return true; } } } + + /// + /// Converts an object to and from JSON. + /// + /// + public abstract class JsonConverter : JsonConverter + { + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (!(value != null ? value is T : ReflectionUtils.IsNullable(typeof(T)))) + { + throw new JsonSerializationException("This converter cannot convert {0} of type {1}".FormatWith(CultureInfo.InvariantCulture, value, value?.GetType())); + } + WriteJson(writer, (T)value, serializer); + } + + /// + /// Writes the JSON representation of the object. + /// + /// The to write to. + /// The value. + /// The calling serializer. + public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer); + + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var existingIsNull = existingValue == null; + if (!(existingIsNull || existingValue is T)) + { + throw new JsonSerializationException("This converter cannot convert {0} of type {1}".FormatWith(CultureInfo.InvariantCulture, existingValue, existingValue.GetType())); + } + return ReadJson(reader, objectType, !existingIsNull, existingIsNull ? default(T) : (T)existingValue, serializer); + } + + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value has a value. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + public abstract T ReadJson(JsonReader reader, Type objectType, bool existingHasValue, T existingValue, JsonSerializer serializer); + + /// + /// Determines whether this instance can convert the specified object type. + /// + /// Type of the object. + /// + /// true if this instance can convert the specified object type; otherwise, false. + /// + public override bool CanConvert(Type objectType) + { + return typeof(T).IsAssignableFrom(objectType); + } + } } \ No newline at end of file