diff --git a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs index 533e113d..c2da6c3a 100644 --- a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs @@ -34,7 +34,7 @@ namespace Newtonsoft.Json.Converters /// Converts a to and from JSON and BSON. /// [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] - public class BsonObjectIdConverter : JsonConverter + public class BsonObjectIdConverter : JsonConverter { /// /// Writes the JSON representation of the object. @@ -42,18 +42,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); } } @@ -62,10 +60,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) { @@ -76,17 +75,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 f75d7e55..c7a436f6 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 7046c292..faba9420 100644 --- a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -37,7 +37,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. @@ -45,14 +45,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) @@ -78,19 +77,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)) @@ -231,18 +231,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/VersionConverter.cs b/Src/Newtonsoft.Json/Converters/VersionConverter.cs index df52718f..575f4b59 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 3f04f620..245ca4a6 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 { @@ -81,4 +82,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