From 0f584a6d52de94b5226a5eaff31539e39571104c Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 2 May 2015 19:40:44 +1200 Subject: [PATCH] -Added JsonRequiredProperty -Added JsonSerializerSettings.ReferenceResolverProvider property -Marked JsonSerializerSettings.ReferenceResolver as obsolete --- .../Properties/AssemblyInfo.cs | 2 +- .../Converters/DataTableConverterTests.cs | 1 - .../Samples/Linq/CreateJsonDeclaratively.cs | 1 + .../DeserializeImmutableCollections.cs | 1 - .../SerializeImmutableCollections.cs | 1 - .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/JsonSerializerTest.cs | 201 ++++++++++++++++++ .../Serialization/TraceWriterTests.cs | 8 +- Src/Newtonsoft.Json/JsonRequiredAttribute.cs | 39 ++++ Src/Newtonsoft.Json/JsonSerializer.cs | 10 +- Src/Newtonsoft.Json/JsonSerializerSettings.cs | 18 +- .../Newtonsoft.Json.Net20.csproj | 1 + .../Newtonsoft.Json.Net35.csproj | 1 + .../Newtonsoft.Json.Net40.csproj | 1 + .../Newtonsoft.Json.Portable.csproj | 1 + .../Newtonsoft.Json.Portable40.csproj | 1 + Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 1 + .../Properties/AssemblyInfo.cs | 2 +- .../Serialization/DefaultContractResolver.cs | 22 +- .../JsonSerializerInternalReader.cs | 22 +- .../Serialization/MemoryTraceWriter.cs | 11 +- .../Serialization/TraceJsonReader.cs | 5 +- .../Serialization/TraceJsonWriter.cs | 5 +- 23 files changed, 319 insertions(+), 38 deletions(-) create mode 100644 Src/Newtonsoft.Json/JsonRequiredAttribute.cs diff --git a/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs index 1f1c0811..17efc85f 100644 --- a/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.TestConsole/Properties/AssemblyInfo.cs @@ -57,4 +57,4 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.1.18407")] +[assembly: AssemblyFileVersion("7.0.1.18502")] diff --git a/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs index f0566ed5..c30a011e 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/DataTableConverterTests.cs @@ -425,7 +425,6 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual("item!", pair2.Key.Rows[0]["item"]); } - [Test] public void SerializedTypedDataTable() { diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Linq/CreateJsonDeclaratively.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Linq/CreateJsonDeclaratively.cs index 037a0d38..6c77d826 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Linq/CreateJsonDeclaratively.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Linq/CreateJsonDeclaratively.cs @@ -62,6 +62,7 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Linq }; } + [Test] public void Example() { #region Usage diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/DeserializeImmutableCollections.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/DeserializeImmutableCollections.cs index e68b1851..864912ca 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/DeserializeImmutableCollections.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/DeserializeImmutableCollections.cs @@ -41,7 +41,6 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer public class DeserializeImmutableCollections : TestFixtureBase { [Test] - [Ignore] public void Example() { #region Usage diff --git a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeImmutableCollections.cs b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeImmutableCollections.cs index a44408b7..6b9f4c4d 100644 --- a/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeImmutableCollections.cs +++ b/Src/Newtonsoft.Json.Tests/Documentation/Samples/Serializer/SerializeImmutableCollections.cs @@ -41,7 +41,6 @@ namespace Newtonsoft.Json.Tests.Documentation.Samples.Serializer public class SerializeImmutableCollections : TestFixtureBase { [Test] - [Ignore] public void Example() { #region Usage diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 3ca773b8..79c8d30e 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -76,4 +76,4 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.1.18407")] +[assembly: AssemblyFileVersion("7.0.1.18502")] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index a4b42f7a..87eb00d6 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -146,6 +146,161 @@ namespace Newtonsoft.Json.Tests.Serialization } #endif + public class RequiredPropertyTestClass + { + [JsonRequired] + internal string Name { get; set; } + } + + [Test] + public void RequiredPropertyTest() + { + RequiredPropertyTestClass c1 = new RequiredPropertyTestClass(); + + ExceptionAssert.Throws( + () => JsonConvert.SerializeObject(c1), + "Cannot write a null value for property 'Name'. Property requires a value. Path ''."); + + RequiredPropertyTestClass c2 = new RequiredPropertyTestClass + { + Name = "Name!" + }; + + string json = JsonConvert.SerializeObject(c2); + + Assert.AreEqual(@"{""Name"":""Name!""}", json); + + ExceptionAssert.Throws( + () => JsonConvert.DeserializeObject(@"{}"), + "Required property 'Name' not found in JSON. Path '', line 1, position 2."); + + ExceptionAssert.Throws( + () => JsonConvert.DeserializeObject(@"{""Name"":null}"), + "Required property 'Name' expects a value but got null. Path '', line 1, position 13."); + + RequiredPropertyTestClass c3 = JsonConvert.DeserializeObject(@"{""Name"":""Name!""}"); + + Assert.AreEqual("Name!", c3.Name); + } + + public class RequiredPropertyConstructorTestClass + { + public RequiredPropertyConstructorTestClass(string name) + { + Name = name; + } + + [JsonRequired] + internal string Name { get; set; } + } + + [Test] + public void RequiredPropertyConstructorTest() + { + RequiredPropertyConstructorTestClass c1 = new RequiredPropertyConstructorTestClass(null); + + ExceptionAssert.Throws( + () => JsonConvert.SerializeObject(c1), + "Cannot write a null value for property 'Name'. Property requires a value. Path ''."); + + RequiredPropertyConstructorTestClass c2 = new RequiredPropertyConstructorTestClass("Name!"); + + string json = JsonConvert.SerializeObject(c2); + + Assert.AreEqual(@"{""Name"":""Name!""}", json); + + ExceptionAssert.Throws( + () => JsonConvert.DeserializeObject(@"{}"), + "Required property 'Name' not found in JSON. Path '', line 1, position 2."); + + RequiredPropertyConstructorTestClass c3 = JsonConvert.DeserializeObject(@"{""Name"":""Name!""}"); + + Assert.AreEqual("Name!", c3.Name); + } + + public class IgnoredPropertiesTestClass + { + [JsonIgnore] + public Version IgnoredProperty { get; set; } + [JsonIgnore] + public List IgnoredList { get; set; } + [JsonIgnore] + public Dictionary IgnoredDictionary { get; set; } + [JsonProperty(Required = Required.Always)] + public string Name { get; set; } + } + + public class IgnoredPropertiesContractResolver : DefaultContractResolver + { + public override JsonContract ResolveContract(Type type) + { + if (type == typeof(Version)) + throw new Exception("Error!"); + + return base.ResolveContract(type); + } + } + + [Test] + public void NeverResolveIgnoredPropertyTypes() + { + Version v = new Version(1, 2, 3, 4); + + IgnoredPropertiesTestClass c1 = new IgnoredPropertiesTestClass + { + IgnoredProperty = v, + IgnoredList = new List + { + v + }, + IgnoredDictionary = new Dictionary + { + { "Value", v } + }, + Name = "Name!" + }; + + string json = JsonConvert.SerializeObject(c1, Formatting.Indented, new JsonSerializerSettings + { + ContractResolver = new IgnoredPropertiesContractResolver() + }); + + Assert.AreEqual(@"{ + ""Name"": ""Name!"" +}", json); + + string deserializeJson = @"{ + ""IgnoredList"": [ + { + ""Major"": 1, + ""Minor"": 2, + ""Build"": 3, + ""Revision"": 4, + ""MajorRevision"": 0, + ""MinorRevision"": 4 + } + ], + ""IgnoredDictionary"": { + ""Value"": { + ""Major"": 1, + ""Minor"": 2, + ""Build"": 3, + ""Revision"": 4, + ""MajorRevision"": 0, + ""MinorRevision"": 4 + } + }, + ""Name"": ""Name!"" +}"; + + IgnoredPropertiesTestClass c2 = JsonConvert.DeserializeObject(deserializeJson, new JsonSerializerSettings + { + ContractResolver = new IgnoredPropertiesContractResolver() + }); + + Assert.AreEqual("Name!", c2.Name); + } + #if !(NETFX_CORE || DNXCORE50 || NET20) [MetadataType(typeof(CustomerValidation))] public partial class CustomerWithMetadataType @@ -721,8 +876,14 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual(ReferenceLoopHandling.Ignore, settings.ReferenceLoopHandling); IdReferenceResolver referenceResolver = new IdReferenceResolver(); +#pragma warning disable 618 settings.ReferenceResolver = referenceResolver; Assert.AreEqual(referenceResolver, settings.ReferenceResolver); +#pragma warning restore 618 + Assert.AreEqual(referenceResolver, settings.ReferenceResolverProvider()); + + settings.ReferenceResolverProvider = () => referenceResolver; + Assert.AreEqual(referenceResolver, settings.ReferenceResolverProvider()); settings.StringEscapeHandling = StringEscapeHandling.EscapeNonAscii; Assert.AreEqual(StringEscapeHandling.EscapeNonAscii, settings.StringEscapeHandling); @@ -8050,7 +8211,9 @@ Path '', line 1, position 1."); string json = JsonConvert.SerializeObject(people, new JsonSerializerSettings { +#pragma warning disable 618 ReferenceResolver = new IdReferenceResolver(), +#pragma warning restore 618 PreserveReferencesHandling = PreserveReferencesHandling.Objects, Formatting = Formatting.Indented }); @@ -8112,7 +8275,45 @@ Path '', line 1, position 1."); IList people = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { +#pragma warning disable 618 ReferenceResolver = new IdReferenceResolver(), +#pragma warning restore 618 + PreserveReferencesHandling = PreserveReferencesHandling.Objects, + Formatting = Formatting.Indented + }); + + Assert.AreEqual(2, people.Count); + + PersonReference john = people[0]; + PersonReference jane = people[1]; + + Assert.AreEqual(john, jane.Spouse); + Assert.AreEqual(jane, john.Spouse); + } + + [Test] + public void DeserializeCustomReferenceResolver_ViaProvider() + { + string json = @"[ + { + ""$id"": ""0b64ffdf-d155-44ad-9689-58d9adb137f3"", + ""Name"": ""John Smith"", + ""Spouse"": { + ""$id"": ""ae3c399c-058d-431d-91b0-a36c266441b9"", + ""Name"": ""Jane Smith"", + ""Spouse"": { + ""$ref"": ""0b64ffdf-d155-44ad-9689-58d9adb137f3"" + } + } + }, + { + ""$ref"": ""ae3c399c-058d-431d-91b0-a36c266441b9"" + } +]"; + + IList people = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings + { + ReferenceResolverProvider = () => new IdReferenceResolver(), PreserveReferencesHandling = PreserveReferencesHandling.Objects, Formatting = Formatting.Indented }); diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs index 528d555e..4e12faef 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TraceWriterTests.cs @@ -876,7 +876,7 @@ Newtonsoft.Json Error: 0 : Error! traceWriter.Flush(); traceWriter.Close(); - StringAssert.AreEqual(@"{ + string json = @"{ ""Array"": [ ""String!"", ""2000-12-12T12:12:12Z"", @@ -927,7 +927,9 @@ Newtonsoft.Json Error: 0 : Error! ) /*A comment*/ ] -}", traceWriter.GetJson()); +}"; + + StringAssert.AreEqual("Serialized JSON: " + Environment.NewLine + json, traceWriter.GetSerializedJsonMessage()); } [Test] @@ -1035,7 +1037,7 @@ Newtonsoft.Json Error: 0 : Error! traceReader.Close(); - StringAssert.AreEqual(json, traceReader.GetJson()); + StringAssert.AreEqual("Deserialized JSON: " + Environment.NewLine + json, traceReader.GetDeserializedJsonMessage()); } #endif } diff --git a/Src/Newtonsoft.Json/JsonRequiredAttribute.cs b/Src/Newtonsoft.Json/JsonRequiredAttribute.cs new file mode 100644 index 00000000..625a23a6 --- /dev/null +++ b/Src/Newtonsoft.Json/JsonRequiredAttribute.cs @@ -0,0 +1,39 @@ +#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 + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Newtonsoft.Json +{ + /// + /// Instructs the to always serialize the member, and require the member has a value. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] + public sealed class JsonRequiredAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index c8cb112b..f7231a7c 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -559,8 +559,8 @@ namespace Newtonsoft.Json if (settings.ContractResolver != null) serializer.ContractResolver = settings.ContractResolver; - if (settings.ReferenceResolver != null) - serializer.ReferenceResolver = settings.ReferenceResolver; + if (settings.ReferenceResolverProvider != null) + serializer.ReferenceResolver = settings.ReferenceResolverProvider(); if (settings.TraceWriter != null) serializer.TraceWriter = settings.TraceWriter; if (settings.Binder != null) @@ -638,7 +638,7 @@ namespace Newtonsoft.Json serializerReader.Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) - TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null); + TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } @@ -710,7 +710,7 @@ namespace Newtonsoft.Json object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) - TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null); + TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); @@ -925,7 +925,7 @@ namespace Newtonsoft.Json serializerWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) - TraceWriter.Trace(TraceLevel.Verbose, "Serialized JSON: " + Environment.NewLine + traceJsonWriter.GetJson(), null); + TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); // reset writer back to previous options if (previousFormatting != null) diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index 089729c4..903c8e25 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -203,7 +203,23 @@ namespace Newtonsoft.Json /// Gets or sets the used by the serializer when resolving references. /// /// The reference resolver. - public IReferenceResolver ReferenceResolver { get; set; } + [ObsoleteAttribute("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] + public IReferenceResolver ReferenceResolver + { + get + { + if (ReferenceResolverProvider == null) + return null; + return ReferenceResolverProvider(); + } + set { ReferenceResolverProvider = () => value; } + } + + /// + /// Gets or sets a function that creates the used by the serializer when resolving references. + /// + /// A function that creates the used by the serializer when resolving references. + public Func ReferenceResolverProvider { get; set; } /// /// Gets or sets the used by the serializer when writing trace messages. diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 8ccf90ca..c06f2f41 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -108,6 +108,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index c56ce389..28cdfedf 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -120,6 +120,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index a75d290d..c98380df 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -121,6 +121,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj index b3c798b9..13cd89d0 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj @@ -94,6 +94,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj index 6a8fb1e0..a77ce560 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj @@ -99,6 +99,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index 63db3c2d..216b9d9f 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -92,6 +92,7 @@ + diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index a65bf1b6..fa5f8396 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -92,5 +92,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.1.18407")] +[assembly: AssemblyFileVersion("7.0.1.18502")] [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 6bc471db..c8316f47 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -308,6 +308,8 @@ namespace Newtonsoft.Json.Serialization // or are a field if serializing just fields if (JsonTypeReflector.GetAttribute(member) != null) serializableMembers.Add(member); + else if (JsonTypeReflector.GetAttribute(member) != null) + serializableMembers.Add(member); #if !NET20 else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute(member) != null) serializableMembers.Add(member); @@ -1222,8 +1224,7 @@ namespace Newtonsoft.Json.Serialization #endif JsonPropertyAttribute propertyAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - if (propertyAttribute != null) - property.HasMemberAttribute = true; + JsonRequiredAttribute requiredAttribute = JsonTypeReflector.GetAttribute(attributeProvider); string mappedName; if (propertyAttribute != null && propertyAttribute.PropertyName != null) @@ -1255,6 +1256,13 @@ namespace Newtonsoft.Json.Serialization hasMemberAttribute = true; } #endif + if (requiredAttribute != null) + { + property._required = Required.Always; + hasMemberAttribute = true; + } + + property.HasMemberAttribute = hasMemberAttribute; bool hasJsonIgnoreAttribute = JsonTypeReflector.GetAttribute(attributeProvider) != null @@ -1310,18 +1318,10 @@ namespace Newtonsoft.Json.Serialization if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic) allowNonPublicAccess = true; #pragma warning restore 618 - if (propertyAttribute != null) + if (hasMemberAttribute) allowNonPublicAccess = true; if (memberSerialization == MemberSerialization.Fields) allowNonPublicAccess = true; - -#if !NET20 - if (dataMemberAttribute != null) - { - allowNonPublicAccess = true; - property.HasMemberAttribute = true; - } -#endif } private Predicate CreateShouldSerializeTest(MemberInfo member) diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 748077d2..220362e6 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -1958,10 +1958,15 @@ namespace Newtonsoft.Json.Serialization continue; } - if (property.PropertyContract == null) - property.PropertyContract = GetContractSafe(property.PropertyType); + JsonConverter propertyConverter = null; - JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member); + if (!property.Ignored) + { + if (property.PropertyContract == null) + property.PropertyContract = GetContractSafe(property.PropertyType); + + propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member); + } if (!ReadForType(reader, property.PropertyContract, propertyConverter != null)) throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); @@ -2060,11 +2065,14 @@ namespace Newtonsoft.Json.Serialization if (resolvedRequired == Required.AllowNull || resolvedRequired == Required.Always) throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); - if (property.PropertyContract == null) - property.PropertyContract = GetContractSafe(property.PropertyType); + if (!property.Ignored) + { + if (property.PropertyContract == null) + property.PropertyContract = GetContractSafe(property.PropertyType); - if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable && !property.Ignored) - property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); + if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable) + property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); + } break; case PropertyPresence.Null: if (resolvedRequired == Required.Always) diff --git a/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs b/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs index f8ed8bac..093c34cb 100644 --- a/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs @@ -41,12 +41,17 @@ namespace Newtonsoft.Json.Serialization /// The trace exception. This parameter is optional. public void Trace(TraceLevel level, string message, Exception ex) { - string traceMessage = DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture) + " " + level.ToString("g") + " " + message; - if (_traceMessages.Count >= 1000) _traceMessages.Dequeue(); - _traceMessages.Enqueue(traceMessage); + StringBuilder sb = new StringBuilder(); + sb.Append(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture)); + sb.Append(" "); + sb.Append(level.ToString("g")); + sb.Append(" "); + sb.Append(message); + + _traceMessages.Enqueue(sb.ToString()); } /// diff --git a/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs b/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs index 4b12c0d5..79a49c9f 100644 --- a/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs +++ b/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs @@ -17,11 +17,14 @@ namespace Newtonsoft.Json.Serialization _innerReader = innerReader; _sw = new StringWriter(CultureInfo.InvariantCulture); + // prefix the message in the stringwriter to avoid concat with a potentially large JSON string + _sw.Write("Deserialized JSON: " + Environment.NewLine); + _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; } - public string GetJson() + public string GetDeserializedJsonMessage() { return _sw.ToString(); } diff --git a/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs b/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs index cd8c4a17..93d4a8bc 100644 --- a/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs @@ -20,6 +20,9 @@ namespace Newtonsoft.Json.Serialization _innerWriter = innerWriter; _sw = new StringWriter(CultureInfo.InvariantCulture); + // prefix the message in the stringwriter to avoid concat with a potentially large JSON string + _sw.Write("Serialized JSON: " + Environment.NewLine); + _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; _textWriter.Culture = innerWriter.Culture; @@ -29,7 +32,7 @@ namespace Newtonsoft.Json.Serialization _textWriter.FloatFormatHandling = innerWriter.FloatFormatHandling; } - public string GetJson() + public string GetSerializedJsonMessage() { return _sw.ToString(); }