From 01c3d48ecf43c547c33c15c80377726f224fecb2 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 9 Feb 2013 23:17:05 +1300 Subject: [PATCH] -Change FloatFormatHandling.Zero to DefaultValue -Documentation --- Build/build.ps1 | 2 +- .../JsonTextWriterTest.cs | 16 ++- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonSerializerTest.cs | 37 ++++++ .../Converters/StringEnumConverter.cs | 5 - Src/Newtonsoft.Json/FloatFormatHandling.cs | 43 ++++++- Src/Newtonsoft.Json/JsonConvert.cs | 14 +-- Src/Newtonsoft.Json/JsonSerializer.cs | 11 ++ Src/Newtonsoft.Json/JsonSerializerSettings.cs | 11 ++ Src/Newtonsoft.Json/JsonTextWriter.cs | 38 +++++- Src/Newtonsoft.Json/JsonWriter.cs | 116 ++++++++++++++++++ .../Newtonsoft.Json.Net20.csproj | 3 +- .../Newtonsoft.Json.Net35.csproj | 4 +- .../Newtonsoft.Json.Portable.csproj | 4 + .../Newtonsoft.Json.Silverlight.csproj | 3 +- .../Newtonsoft.Json.WindowsPhone.csproj | 4 + Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 3 +- .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonPrimitiveContract.cs | 5 + .../JsonSerializerInternalWriter.cs | 12 +- 20 files changed, 307 insertions(+), 28 deletions(-) diff --git a/Build/build.ps1 b/Build/build.ps1 index b93028eb..552603cf 100644 --- a/Build/build.ps1 +++ b/Build/build.ps1 @@ -154,7 +154,7 @@ function GetConstants($constants, $includeSigned) { $signed = switch($includeSigned) { $true { ";SIGNED" } default { "" } } - return "/p:DefineConstants=`"TRACE;$constants$signed`"" + return "/p:DefineConstants=`"CODE_ANALYSIS;TRACE;$constants$signed`"" } function GetVersion($majorVersion) diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs index 0b9349e9..4b0f4e07 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs @@ -433,7 +433,7 @@ namespace Newtonsoft.Json.Tests using (JsonWriter jsonWriter = new JsonTextWriter(sw)) { jsonWriter.Formatting = Formatting.Indented; - jsonWriter.FloatFormatHandling = FloatFormatHandling.Zero; + jsonWriter.FloatFormatHandling = FloatFormatHandling.DefaultValue; jsonWriter.WriteStartArray(); jsonWriter.WriteValue(double.NaN); @@ -442,6 +442,12 @@ namespace Newtonsoft.Json.Tests jsonWriter.WriteValue(float.NaN); jsonWriter.WriteValue(float.PositiveInfinity); jsonWriter.WriteValue(float.NegativeInfinity); + jsonWriter.WriteValue((double?)double.NaN); + jsonWriter.WriteValue((double?)double.PositiveInfinity); + jsonWriter.WriteValue((double?)double.NegativeInfinity); + jsonWriter.WriteValue((float?)float.NaN); + jsonWriter.WriteValue((float?)float.PositiveInfinity); + jsonWriter.WriteValue((float?)float.NegativeInfinity); jsonWriter.WriteEndArray(); jsonWriter.Flush(); @@ -453,7 +459,13 @@ namespace Newtonsoft.Json.Tests 0.0, 0.0, 0.0, - 0.0 + 0.0, + null, + null, + null, + null, + null, + null ]"; string result = sb.ToString(); diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 1be61ecc..be1abd51 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -76,5 +76,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.11.15802")] +[assembly: AssemblyFileVersion("4.5.11.15809")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 226dc6e6..5b7a27c0 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -7124,6 +7124,43 @@ Parameter name: value", Assert.AreEqual("07/19/2012 14:30:00 +09:30", dateTimeOffset.ToString(CultureInfo.InvariantCulture)); } + public class NullableFloats + { + public object Object { get; set; } + public float Float { get; set; } + public double Double { get; set; } + public float? NullableFloat { get; set; } + public double? NullableDouble { get; set; } + public object ObjectNull { get; set; } + } + + [Test] + public void NullableFloatingPoint() + { + NullableFloats floats = new NullableFloats + { + Object = double.NaN, + ObjectNull = null, + Float = float.NaN, + NullableDouble = double.NaN, + NullableFloat = null + }; + + string json = JsonConvert.SerializeObject(floats, Formatting.Indented, new JsonSerializerSettings + { + FloatFormatHandling = FloatFormatHandling.DefaultValue + }); + + Assert.AreEqual(@"{ + ""Object"": 0.0, + ""Float"": 0.0, + ""Double"": 0.0, + ""NullableFloat"": null, + ""NullableDouble"": null, + ""ObjectNull"": null +}", json); + } + [Test] public void DateFormatString() { diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index 022e4c6f..cdf5a350 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -131,11 +131,6 @@ namespace Newtonsoft.Json.Converters throw JsonSerializationException.Create(reader, "Unexpected token when parsing enum. Expected String or Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - /// - /// A cached representation of the Enum string representation to respect per Enum field name. - /// - /// The type of the Enum. - /// A map of enum field name to either the field name, or the configured enum member name (). private BidirectionalDictionary GetEnumNameMap(Type t) { BidirectionalDictionary map; diff --git a/Src/Newtonsoft.Json/FloatFormatHandling.cs b/Src/Newtonsoft.Json/FloatFormatHandling.cs index ddb2a22a..28fc0ddc 100644 --- a/Src/Newtonsoft.Json/FloatFormatHandling.cs +++ b/Src/Newtonsoft.Json/FloatFormatHandling.cs @@ -1,9 +1,48 @@ -namespace Newtonsoft.Json +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +namespace Newtonsoft.Json { + /// + /// Specifies float format handling options when writing special floating point values, e.g. , + /// and with . + /// public enum FloatFormatHandling { + /// + /// Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity". + /// String, + /// + /// Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity. + /// Note that this will produce non-valid JSON. + /// Symbol, - Zero + /// + /// Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a property. + /// + DefaultValue } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index fbed1d8c..02dbf62a 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -446,18 +446,18 @@ namespace Newtonsoft.Json return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } - internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar) + internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { - return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar); + return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } - private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar) + private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value))) return text; - if (floatFormatHandling == FloatFormatHandling.Zero) - return "0.0"; + if (floatFormatHandling == FloatFormatHandling.DefaultValue) + return (!nullable) ? "0.0" : Null; return quoteChar + text + quoteChar; } @@ -472,9 +472,9 @@ namespace Newtonsoft.Json return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } - internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar) + internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { - return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar); + return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index babc6200..72bd98a5 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -346,18 +346,29 @@ namespace Newtonsoft.Json set { _dateParseHandling = value; } } + /// + /// Get or set how special floating point values, e.g. , + /// and , + /// are written as JSON. + /// public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling ?? JsonSerializerSettings.DefaultFloatFormatHandling; } set { _floatFormatHandling = value; } } + /// + /// Get or set how strings are escaped when writing JSON text. + /// public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling ?? JsonSerializerSettings.DefaultStringEscapeHandling; } set { _stringEscapeHandling = value; } } + /// + /// Get or set how and values are formatting when writing JSON text. + /// public virtual string DateFormatString { get { return _dateFormatString ?? JsonSerializerSettings.DefaultDateFormatString; } diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index 2204d98b..991858ab 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -168,6 +168,9 @@ namespace Newtonsoft.Json /// The context. public StreamingContext Context { get; set; } + /// + /// Get or set how and values are formatting when writing JSON text. + /// public string DateFormatString { get { return _dateFormatString ?? DefaultDateFormatString; } @@ -230,12 +233,20 @@ namespace Newtonsoft.Json set { _dateParseHandling = value; } } + /// + /// Get or set how special floating point values, e.g. , + /// and , + /// are written as JSON. + /// public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling ?? DefaultFloatFormatHandling; } set { _floatFormatHandling = value; } } + /// + /// Get or set how strings are escaped when writing JSON text. + /// public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling ?? DefaultStringEscapeHandling; } diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 0f2e16f0..82621245 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -357,7 +357,24 @@ namespace Newtonsoft.Json public override void WriteValue(float value) { InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar), JsonToken.Float); + WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(float? value) + { + if (value == null) + { + WriteNull(); + } + else + { + InternalWriteValue(JsonToken.Float); + WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float); + } } /// @@ -367,7 +384,24 @@ namespace Newtonsoft.Json public override void WriteValue(double value) { InternalWriteValue(JsonToken.Float); - WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar), JsonToken.Float); + WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float); + } + + /// + /// Writes a value. + /// + /// The value to write. + public override void WriteValue(double? value) + { + if (value == null) + { + WriteNull(); + } + else + { + InternalWriteValue(JsonToken.Float); + WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float); + } } /// diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index b4300aee..d4c1fcca 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -250,18 +250,29 @@ namespace Newtonsoft.Json set { _stringEscapeHandling = value; } } + /// + /// Get or set how special floating point values, e.g. , + /// and , + /// are written to JSON text. + /// public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling; } set { _floatFormatHandling = value; } } + /// + /// Get or set how and values are formatting when writing JSON text. + /// public string DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } + /// + /// Gets or sets the culture used when writing JSON. Defaults to . + /// public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } @@ -1301,6 +1312,111 @@ namespace Newtonsoft.Json throw JsonWriterException.Create(this, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } + + /// + /// Writes a value. + /// An error will raised if the value cannot be written as a single JSON token. + /// + /// The value to write. + /// A flag indicating whether the value is nullable. + public virtual void WriteValue(object value, bool nullable) + { + if (!nullable) + WriteValue(value); + + if (value == null) + { + WriteNull(); + return; + } + else if (ConvertUtils.IsConvertible(value)) + { + IConvertible convertible = ConvertUtils.ToConvertible(value); + + switch (convertible.GetTypeCode()) + { + case TypeCode.String: + WriteValue(convertible.ToString(CultureInfo.InvariantCulture)); + return; + case TypeCode.Char: + WriteValue((char?)convertible.ToChar(CultureInfo.InvariantCulture)); + return; + case TypeCode.Boolean: + WriteValue((bool?)convertible.ToBoolean(CultureInfo.InvariantCulture)); + return; + case TypeCode.SByte: + WriteValue((sbyte?)convertible.ToSByte(CultureInfo.InvariantCulture)); + return; + case TypeCode.Int16: + WriteValue((short?)convertible.ToInt16(CultureInfo.InvariantCulture)); + return; + case TypeCode.UInt16: + WriteValue((ushort?)convertible.ToUInt16(CultureInfo.InvariantCulture)); + return; + case TypeCode.Int32: + WriteValue((int?)convertible.ToInt32(CultureInfo.InvariantCulture)); + return; + case TypeCode.Byte: + WriteValue((byte?)convertible.ToByte(CultureInfo.InvariantCulture)); + return; + case TypeCode.UInt32: + WriteValue((uint?)convertible.ToUInt32(CultureInfo.InvariantCulture)); + return; + case TypeCode.Int64: + WriteValue((long?)convertible.ToInt64(CultureInfo.InvariantCulture)); + return; + case TypeCode.UInt64: + WriteValue((ulong?)convertible.ToUInt64(CultureInfo.InvariantCulture)); + return; + case TypeCode.Single: + WriteValue((float?)convertible.ToSingle(CultureInfo.InvariantCulture)); + return; + case TypeCode.Double: + WriteValue((double?)convertible.ToDouble(CultureInfo.InvariantCulture)); + return; + case TypeCode.DateTime: + WriteValue((DateTime?)convertible.ToDateTime(CultureInfo.InvariantCulture)); + return; + case TypeCode.Decimal: + WriteValue((decimal?)convertible.ToDecimal(CultureInfo.InvariantCulture)); + return; +#if !(NETFX_CORE || PORTABLE) + case TypeCode.DBNull: + WriteNull(); + return; +#endif + } + } +#if !PocketPC && !NET20 + else if (value is DateTimeOffset) + { + WriteValue((DateTimeOffset?)value); + return; + } +#endif + else if (value is byte[]) + { + WriteValue((byte[])value); + return; + } + else if (value is Guid) + { + WriteValue((Guid?)value); + return; + } + else if (value is Uri) + { + WriteValue((Uri)value); + return; + } + else if (value is TimeSpan) + { + WriteValue((TimeSpan?)value); + return; + } + + throw JsonWriterException.Create(this, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); + } #endregion /// diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 5f3418b4..3558d106 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -65,7 +65,8 @@ prompt 4 bin\Release\Net20\Newtonsoft.Json.xml - AllRules.ruleset + Newtonsoft.Json.ruleset + true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index a2edc5ce..a878e53b 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -66,8 +66,8 @@ prompt 4 bin\Release\Net35\Newtonsoft.Json.xml - ..\..\..\..\trunk\Src\Newtonsoft.Json\Newtonsoft.Json.ruleset - false + Newtonsoft.Json.ruleset + true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj index f8e1b993..3ee8e7ba 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj @@ -21,6 +21,8 @@ TRACE;DEBUG;PORTABLE prompt 4 + true + Newtonsoft.Json.ruleset pdbonly @@ -30,6 +32,8 @@ prompt 4 bin\Release\Portable\Newtonsoft.Json.xml + true + Newtonsoft.Json.ruleset diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj index 65c0b8d4..848620fa 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj @@ -67,7 +67,8 @@ prompt 4 Bin\Release\Silverlight\Newtonsoft.Json.xml - AllRules.ruleset + Newtonsoft.Json.ruleset + true diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj index b5f31243..f25f1359 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj @@ -31,6 +31,8 @@ 4 + true + Newtonsoft.Json.ruleset pdbonly @@ -42,6 +44,8 @@ prompt 4 Bin\Release\WindowsPhone\Newtonsoft.Json.xml + true + Newtonsoft.Json.ruleset diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index b651482e..55db63fc 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -66,8 +66,9 @@ prompt 4 bin\Release\Net40\Newtonsoft.Json.xml - AllRules.ruleset + Newtonsoft.Json.ruleset true + true diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index ec881814..c9794905 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -90,7 +90,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.11.15802")] +[assembly: AssemblyFileVersion("4.5.11.15809")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs index ddd1629e..f3ff93b5 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs @@ -24,6 +24,7 @@ #endregion using System; +using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Serialization { @@ -32,6 +33,8 @@ namespace Newtonsoft.Json.Serialization /// public class JsonPrimitiveContract : JsonContract { + internal bool Nullable { get; set; } + /// /// Initializes a new instance of the class. /// @@ -40,6 +43,8 @@ namespace Newtonsoft.Json.Serialization : base(underlyingType) { ContractType = JsonContractType.Primitive; + + Nullable = ReflectionUtils.IsNullable(underlyingType); } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 400cd3ab..400479fb 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -88,13 +88,21 @@ namespace Newtonsoft.Json.Serialization writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName(JsonTypeReflector.ValuePropertyName); - writer.WriteValue(value); + + if (contract.IsNullable) + writer.WriteValue(value, true); + else + writer.WriteValue(value); + writer.WriteEndObject(); return; } } - writer.WriteValue(value); + if (contract.IsNullable) + writer.WriteValue(value, true); + else + writer.WriteValue(value); } private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)