From cdf10151d507d497a3f9a71d36d544b199f73435 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 29 Jul 2019 09:13:42 +1200 Subject: [PATCH] Update Newtonsoft.Json project to use nullable reference types (#1950) --- Build/build.ps1 | 2 +- .../Converters/XmlNodeConverterTest.cs | 16 + Src/Newtonsoft.Json.Tests/JsonConvertTest.cs | 17 +- Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs | 20 ++ .../Linq/JsonPath/QueryExpressionTests.cs | 134 +------ .../Newtonsoft.Json.Tests.csproj | 24 +- .../Serialization/ContractResolverTests.cs | 12 + Src/Newtonsoft.Json.Tests/TestFixtureBase.cs | 8 +- Src/Newtonsoft.Json/Bson/BsonBinaryType.cs | 2 + Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs | 2 + Src/Newtonsoft.Json/Bson/BsonObjectId.cs | 2 + Src/Newtonsoft.Json/Bson/BsonReader.cs | 2 + Src/Newtonsoft.Json/Bson/BsonToken.cs | 2 + Src/Newtonsoft.Json/Bson/BsonType.cs | 2 + Src/Newtonsoft.Json/Bson/BsonWriter.cs | 2 + .../Converters/BinaryConverter.cs | 10 +- .../Converters/BsonObjectIdConverter.cs | 2 + .../Converters/CustomCreationConverter.cs | 4 +- .../Converters/DataSetConverter.cs | 10 +- .../Converters/DataTableConverter.cs | 14 +- .../Converters/DiscriminatedUnionConverter.cs | 78 ++-- .../Converters/EntityKeyMemberConverter.cs | 28 +- .../Converters/ExpandoObjectConverter.cs | 16 +- .../Converters/IsoDateTimeConverter.cs | 16 +- .../Converters/JavaScriptDateTimeConverter.cs | 8 +- .../Converters/KeyValuePairConverter.cs | 20 +- .../Converters/RegexConverter.cs | 16 +- .../Converters/StringEnumConverter.cs | 14 +- .../Converters/UnixDateTimeConverter.cs | 8 +- .../Converters/VersionConverter.cs | 6 +- .../Converters/XmlNodeConverter.cs | 267 +++++++------- Src/Newtonsoft.Json/DefaultJsonNameTable.cs | 2 +- Src/Newtonsoft.Json/IArrayPool.cs | 2 +- Src/Newtonsoft.Json/JsonContainerAttribute.cs | 20 +- Src/Newtonsoft.Json/JsonConvert.cs | 99 +++--- Src/Newtonsoft.Json/JsonConverter.cs | 18 +- Src/Newtonsoft.Json/JsonConverterAttribute.cs | 2 +- Src/Newtonsoft.Json/JsonException.cs | 2 +- Src/Newtonsoft.Json/JsonNameTable.cs | 2 +- Src/Newtonsoft.Json/JsonPosition.cs | 14 +- Src/Newtonsoft.Json/JsonPropertyAttribute.cs | 10 +- Src/Newtonsoft.Json/JsonReader.Async.cs | 10 +- Src/Newtonsoft.Json/JsonReader.cs | 77 ++-- Src/Newtonsoft.Json/JsonReaderException.cs | 8 +- .../JsonSerializationException.cs | 8 +- Src/Newtonsoft.Json/JsonSerializer.cs | 84 ++--- Src/Newtonsoft.Json/JsonSerializerSettings.cs | 22 +- Src/Newtonsoft.Json/JsonTextReader.Async.cs | 56 ++- Src/Newtonsoft.Json/JsonTextReader.cs | 93 ++++- Src/Newtonsoft.Json/JsonTextWriter.Async.cs | 42 ++- Src/Newtonsoft.Json/JsonTextWriter.cs | 35 +- Src/Newtonsoft.Json/JsonValidatingReader.cs | 2 + Src/Newtonsoft.Json/JsonWriter.Async.cs | 24 +- Src/Newtonsoft.Json/JsonWriter.cs | 34 +- Src/Newtonsoft.Json/JsonWriterException.cs | 8 +- Src/Newtonsoft.Json/Linq/Extensions.cs | 17 +- Src/Newtonsoft.Json/Linq/JArray.Async.cs | 2 +- Src/Newtonsoft.Json/Linq/JArray.cs | 17 +- .../Linq/JConstructor.Async.cs | 6 +- Src/Newtonsoft.Json/Linq/JConstructor.cs | 23 +- Src/Newtonsoft.Json/Linq/JContainer.Async.cs | 17 +- Src/Newtonsoft.Json/Linq/JContainer.cs | 117 +++--- Src/Newtonsoft.Json/Linq/JObject.Async.cs | 2 +- Src/Newtonsoft.Json/Linq/JObject.cs | 101 +++--- Src/Newtonsoft.Json/Linq/JProperty.Async.cs | 4 +- Src/Newtonsoft.Json/Linq/JProperty.cs | 50 ++- .../Linq/JPropertyDescriptor.cs | 2 +- .../Linq/JPropertyKeyedCollection.cs | 18 +- Src/Newtonsoft.Json/Linq/JRaw.cs | 2 +- Src/Newtonsoft.Json/Linq/JToken.Async.cs | 8 +- Src/Newtonsoft.Json/Linq/JToken.cs | 187 +++++----- Src/Newtonsoft.Json/Linq/JTokenReader.cs | 26 +- Src/Newtonsoft.Json/Linq/JTokenWriter.cs | 33 +- Src/Newtonsoft.Json/Linq/JValue.Async.cs | 6 +- Src/Newtonsoft.Json/Linq/JValue.cs | 63 ++-- .../Linq/JsonPath/ArrayIndexFilter.cs | 2 +- .../Linq/JsonPath/ArrayMultipleIndexFilter.cs | 9 +- .../Linq/JsonPath/FieldFilter.cs | 13 +- .../Linq/JsonPath/FieldMultipleFilter.cs | 9 +- Src/Newtonsoft.Json/Linq/JsonPath/JPath.cs | 66 ++-- .../Linq/JsonPath/PathFilter.cs | 7 +- .../Linq/JsonPath/QueryExpression.cs | 35 +- .../Linq/JsonPath/QueryFilter.cs | 7 +- .../Linq/JsonPath/QueryScanFilter.cs | 7 +- .../Linq/JsonPath/ScanFilter.cs | 11 +- .../Linq/JsonPath/ScanMultipleFilter.cs | 14 +- Src/Newtonsoft.Json/Newtonsoft.Json.csproj | 7 +- Src/Newtonsoft.Json/Schema/Extensions.cs | 2 + Src/Newtonsoft.Json/Schema/JsonSchema.cs | 2 + .../Schema/JsonSchemaBuilder.cs | 2 + .../Schema/JsonSchemaConstants.cs | 2 + .../Schema/JsonSchemaException.cs | 2 + .../Schema/JsonSchemaGenerator.cs | 2 + Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs | 2 + .../Schema/JsonSchemaModelBuilder.cs | 2 + Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs | 2 + .../Schema/JsonSchemaNodeCollection.cs | 2 + .../Schema/JsonSchemaResolver.cs | 2 + Src/Newtonsoft.Json/Schema/JsonSchemaType.cs | 2 + .../Schema/JsonSchemaWriter.cs | 2 + .../Schema/UndefinedSchemaIdHandling.cs | 2 + .../Schema/ValidationEventArgs.cs | 2 + .../Schema/ValidationEventHandler.cs | 2 + .../Serialization/CachedAttributeGetter.cs | 4 +- .../Serialization/DefaultContractResolver.cs | 137 ++++---- .../DefaultSerializationBinder.cs | 24 +- .../Serialization/DiagnosticsTraceWriter.cs | 2 +- .../Serialization/DynamicValueProvider.cs | 8 +- .../Serialization/ErrorContext.cs | 6 +- .../Serialization/ErrorEventArgs.cs | 4 +- .../Serialization/ExpressionValueProvider.cs | 8 +- .../Serialization/ISerializationBinder.cs | 4 +- .../Serialization/ITraceWriter.cs | 2 +- .../Serialization/IValueProvider.cs | 4 +- .../Serialization/JsonArrayContract.cs | 36 +- .../Serialization/JsonContainerContract.cs | 12 +- .../Serialization/JsonContract.cs | 23 +- .../Serialization/JsonDictionaryContract.cs | 48 +-- .../Serialization/JsonDynamicContract.cs | 16 +- .../Serialization/JsonFormatterConverter.cs | 13 +- .../JsonISerializableContract.cs | 2 +- .../Serialization/JsonObjectContract.cs | 20 +- .../Serialization/JsonProperty.cs | 50 +-- .../Serialization/JsonPropertyCollection.cs | 17 +- .../JsonSerializerInternalBase.cs | 14 +- .../JsonSerializerInternalReader.cs | 332 +++++++++--------- .../JsonSerializerInternalWriter.cs | 129 ++++--- .../Serialization/JsonSerializerProxy.cs | 16 +- .../Serialization/JsonTypeReflector.cs | 60 ++-- .../Serialization/MemoryTraceWriter.cs | 2 +- .../Serialization/NamingStrategy.cs | 2 +- .../Serialization/ObjectConstructor.cs | 2 +- .../Serialization/ReflectionValueProvider.cs | 4 +- .../SerializationBinderAdapter.cs | 4 +- .../Serialization/TraceJsonReader.cs | 12 +- .../Serialization/TraceJsonWriter.cs | 14 +- Src/Newtonsoft.Json/SerializationBinder.cs | 4 +- Src/Newtonsoft.Json/Utilities/AsyncUtils.cs | 8 +- .../Utilities/Base64Encoder.cs | 4 +- .../Utilities/BidirectionalDictionary.cs | 4 +- .../Utilities/CollectionUtils.cs | 9 +- .../Utilities/CollectionWrapper.cs | 38 +- Src/Newtonsoft.Json/Utilities/ConvertUtils.cs | 84 +++-- .../Utilities/DateTimeUtils.cs | 12 +- .../Utilities/DictionaryWrapper.cs | 79 +++-- Src/Newtonsoft.Json/Utilities/DynamicProxy.cs | 16 +- .../Utilities/DynamicProxyMetaObject.cs | 6 +- .../DynamicReflectionDelegateFactory.cs | 24 +- Src/Newtonsoft.Json/Utilities/DynamicUtils.cs | 14 +- Src/Newtonsoft.Json/Utilities/EnumUtils.cs | 26 +- .../ExpressionReflectionDelegateFactory.cs | 47 ++- Src/Newtonsoft.Json/Utilities/FSharpUtils.cs | 42 +-- .../Utilities/ImmutableCollectionsUtils.cs | 6 +- .../Utilities/JavaScriptUtils.cs | 35 +- .../LateBoundReflectionDelegateFactory.cs | 10 +- Src/Newtonsoft.Json/Utilities/LinqBridge.cs | 2 + Src/Newtonsoft.Json/Utilities/MethodBinder.cs | 4 +- Src/Newtonsoft.Json/Utilities/MethodCall.cs | 2 +- .../Utilities/MiscellaneousUtils.cs | 17 +- .../Utilities/NullableAttributes.cs | 55 +++ .../Utilities/ReflectionDelegateFactory.cs | 14 +- .../Utilities/ReflectionObject.cs | 28 +- .../Utilities/ReflectionUtils.cs | 64 ++-- Src/Newtonsoft.Json/Utilities/StringBuffer.cs | 20 +- Src/Newtonsoft.Json/Utilities/StringUtils.cs | 18 +- .../Utilities/TypeExtensions.cs | 36 +- .../Utilities/ValidationUtils.cs | 4 +- Src/global.json | 2 +- azure-pipelines.yml | 2 +- 169 files changed, 2265 insertions(+), 1860 deletions(-) create mode 100644 Src/Newtonsoft.Json/Utilities/NullableAttributes.cs diff --git a/Build/build.ps1 b/Build/build.ps1 index 52eb1b087..2c379a5d8 100644 --- a/Build/build.ps1 +++ b/Build/build.ps1 @@ -14,7 +14,7 @@ $workingName = if ($workingName) {$workingName} else {"Working"} $assemblyVersion = if ($assemblyVersion) {$assemblyVersion} else {$majorVersion + '.0.0'} $netCliChannel = "2.0" - $netCliVersion = "2.2.105" + $netCliVersion = "3.0.100-preview8-013317" $nugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" $baseDir = resolve-path .. diff --git a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs index f420ef6b4..fb7b28be8 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/XmlNodeConverterTest.cs @@ -160,6 +160,14 @@ public void DeserializeXmlNode_DefaultDate() Assert.AreEqual("", xmlNode.OuterXml); } + [Test] + public void XmlNode_Null() + { + string json = JsonConvert.SerializeXmlNode(null); + + Assert.AreEqual("null", json); + } + [Test] public void XmlNode_Roundtrip_PropertyNameWithColon() { @@ -305,6 +313,14 @@ public void WriteJsonNull() } #if !NET20 + [Test] + public void XNode_Null() + { + string json = JsonConvert.SerializeXNode(null); + + Assert.AreEqual("null", json); + } + [Test] public void XNode_UnescapeTextContent() { diff --git a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs index 9862161bf..220ec5c30 100644 --- a/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonConvertTest.cs @@ -1563,14 +1563,15 @@ public class OverloadWithBaseType public int Overload { get; set; } } - [Test] - public void JsonConverterConstructor_OverloadsWithBaseTypes() - { - OverloadWithBaseType value = new OverloadWithBaseType(); - string json = JsonConvert.SerializeObject(value); - - Assert.AreEqual("{\"Overload\":\"IList\"}", json); - } + //[Test] + //[Ignore("https://github.com/dotnet/roslyn/issues/36974")] + //public void JsonConverterConstructor_OverloadsWithBaseTypes() + //{ + // OverloadWithBaseType value = new OverloadWithBaseType(); + // string json = JsonConvert.SerializeObject(value); + + // Assert.AreEqual("{\"Overload\":\"IList\"}", json); + //} [Test] diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index d72dc8d56..f3c00048c 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -242,6 +242,26 @@ public void BeforeAfter() Assert.AreEqual(2, a[2].BeforeSelf().Count()); } + [Test] + public void BeforeSelf_NoParent_ReturnEmpty() + { + JObject o = new JObject(); + + List result = o.BeforeSelf().ToList(); + Assert.AreEqual(0, result.Count); + } + + [Test] + public void BeforeSelf_OnlyChild_ReturnEmpty() + { + JArray a = new JArray(); + JObject o = new JObject(); + a.Add(o); + + List result = o.BeforeSelf().ToList(); + Assert.AreEqual(0, result.Count); + } + [Test] public void Casting() { diff --git a/Src/Newtonsoft.Json.Tests/Linq/JsonPath/QueryExpressionTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JsonPath/QueryExpressionTests.cs index cdb3db070..edabea57c 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JsonPath/QueryExpressionTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JsonPath/QueryExpressionTests.cs @@ -45,33 +45,12 @@ public class QueryExpressionTests : TestFixtureBase [Test] public void AndExpressionTest() { - CompositeExpression compositeExpression = new CompositeExpression + CompositeExpression compositeExpression = new CompositeExpression(QueryOperator.And) { - Operator = QueryOperator.And, Expressions = new List { - new BooleanQueryExpression - { - Operator = QueryOperator.Exists, - Left = new List - { - new FieldFilter - { - Name = "FirstName" - } - } - }, - new BooleanQueryExpression - { - Operator = QueryOperator.Exists, - Left = new List - { - new FieldFilter - { - Name = "LastName" - } - } - } + new BooleanQueryExpression(QueryOperator.Exists, new List { new FieldFilter("FirstName") }, null), + new BooleanQueryExpression(QueryOperator.Exists, new List { new FieldFilter("LastName") }, null) } }; @@ -103,33 +82,12 @@ public void AndExpressionTest() [Test] public void OrExpressionTest() { - CompositeExpression compositeExpression = new CompositeExpression + CompositeExpression compositeExpression = new CompositeExpression(QueryOperator.Or) { - Operator = QueryOperator.Or, Expressions = new List { - new BooleanQueryExpression - { - Operator = QueryOperator.Exists, - Left = new List - { - new FieldFilter - { - Name = "FirstName" - } - } - }, - new BooleanQueryExpression - { - Operator = QueryOperator.Exists, - Left = new List - { - new FieldFilter - { - Name = "LastName" - } - } - } + new BooleanQueryExpression(QueryOperator.Exists, new List { new FieldFilter("FirstName") }, null), + new BooleanQueryExpression(QueryOperator.Exists, new List { new FieldFilter("LastName") }, null) } }; @@ -161,30 +119,14 @@ public void OrExpressionTest() [Test] public void BooleanExpressionTest_RegexEqualsOperator() { - BooleanQueryExpression e1 = new BooleanQueryExpression - { - Operator = QueryOperator.RegexEquals, - Right = new JValue("/foo.*d/"), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e1 = new BooleanQueryExpression(QueryOperator.RegexEquals, new List { new ArrayIndexFilter() }, new JValue("/foo.*d/")); Assert.IsTrue(e1.IsMatch(null, new JArray("food"))); Assert.IsTrue(e1.IsMatch(null, new JArray("fooood and drink"))); Assert.IsFalse(e1.IsMatch(null, new JArray("FOOD"))); Assert.IsFalse(e1.IsMatch(null, new JArray("foo", "foog", "good"))); - BooleanQueryExpression e2 = new BooleanQueryExpression - { - Operator = QueryOperator.RegexEquals, - Right = new JValue("/Foo.*d/i"), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e2 = new BooleanQueryExpression(QueryOperator.RegexEquals, new List { new ArrayIndexFilter() }, new JValue("/Foo.*d/i")); Assert.IsTrue(e2.IsMatch(null, new JArray("food"))); Assert.IsTrue(e2.IsMatch(null, new JArray("fooood and drink"))); @@ -195,28 +137,12 @@ public void BooleanExpressionTest_RegexEqualsOperator() [Test] public void BooleanExpressionTest_RegexEqualsOperator_CornerCase() { - BooleanQueryExpression e1 = new BooleanQueryExpression - { - Operator = QueryOperator.RegexEquals, - Right = new JValue("/// comment/"), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e1 = new BooleanQueryExpression(QueryOperator.RegexEquals, new List { new ArrayIndexFilter() }, new JValue("/// comment/")); Assert.IsTrue(e1.IsMatch(null, new JArray("// comment"))); Assert.IsFalse(e1.IsMatch(null, new JArray("//comment", "/ comment"))); - BooleanQueryExpression e2 = new BooleanQueryExpression - { - Operator = QueryOperator.RegexEquals, - Right = new JValue("/.*/i"), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e2 = new BooleanQueryExpression(QueryOperator.RegexEquals, new List { new ArrayIndexFilter() }, new JValue("/.*/i")); Assert.IsTrue(e2.IsMatch(null, new JArray("Test", ""))); Assert.IsFalse(e2.IsMatch(null, new JArray("Test"))); @@ -225,15 +151,7 @@ public void BooleanExpressionTest_RegexEqualsOperator_CornerCase() [Test] public void BooleanExpressionTest() { - BooleanQueryExpression e1 = new BooleanQueryExpression - { - Operator = QueryOperator.LessThan, - Right = new JValue(3), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e1 = new BooleanQueryExpression(QueryOperator.LessThan, new List { new ArrayIndexFilter() }, new JValue(3)); Assert.IsTrue(e1.IsMatch(null, new JArray(1, 2, 3, 4, 5))); Assert.IsTrue(e1.IsMatch(null, new JArray(2, 3, 4, 5))); @@ -241,15 +159,7 @@ public void BooleanExpressionTest() Assert.IsFalse(e1.IsMatch(null, new JArray(4, 5))); Assert.IsFalse(e1.IsMatch(null, new JArray("11", 5))); - BooleanQueryExpression e2 = new BooleanQueryExpression - { - Operator = QueryOperator.LessThanOrEquals, - Right = new JValue(3), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e2 = new BooleanQueryExpression(QueryOperator.LessThanOrEquals, new List { new ArrayIndexFilter() }, new JValue(3)); Assert.IsTrue(e2.IsMatch(null, new JArray(1, 2, 3, 4, 5))); Assert.IsTrue(e2.IsMatch(null, new JArray(2, 3, 4, 5))); @@ -261,15 +171,7 @@ public void BooleanExpressionTest() [Test] public void BooleanExpressionTest_GreaterThanOperator() { - BooleanQueryExpression e1 = new BooleanQueryExpression - { - Operator = QueryOperator.GreaterThan, - Right = new JValue(3), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e1 = new BooleanQueryExpression(QueryOperator.GreaterThan, new List { new ArrayIndexFilter() }, new JValue(3)); Assert.IsTrue(e1.IsMatch(null, new JArray("2", "26"))); Assert.IsTrue(e1.IsMatch(null, new JArray(2, 26))); @@ -280,15 +182,7 @@ public void BooleanExpressionTest_GreaterThanOperator() [Test] public void BooleanExpressionTest_GreaterThanOrEqualsOperator() { - BooleanQueryExpression e1 = new BooleanQueryExpression - { - Operator = QueryOperator.GreaterThanOrEquals, - Right = new JValue(3), - Left = new List - { - new ArrayIndexFilter() - } - }; + BooleanQueryExpression e1 = new BooleanQueryExpression(QueryOperator.GreaterThanOrEquals, new List { new ArrayIndexFilter() }, new JValue(3)); Assert.IsTrue(e1.IsMatch(null, new JArray("2", "26"))); Assert.IsTrue(e1.IsMatch(null, new JArray(2, 26))); diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj index 66e46a23e..201ee13e0 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.csproj @@ -42,8 +42,8 @@ - - + + @@ -66,8 +66,8 @@ - - + + @@ -89,8 +89,8 @@ - - + + @@ -112,8 +112,8 @@ - - + + @@ -129,8 +129,8 @@ - - + + @@ -144,8 +144,8 @@ - - + + diff --git a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs index ab680666f..35e1e54c8 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/ContractResolverTests.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.IO; @@ -727,6 +728,17 @@ protected virtual bool OnProp4Specified() } } + [Test] + public void NonGenericDictionary_KeyValueTypes() + { + DefaultContractResolver resolver = new DefaultContractResolver(); + + JsonDictionaryContract c = (JsonDictionaryContract)resolver.ResolveContract(typeof(IDictionary)); + + Assert.IsNull(c.DictionaryKeyType); + Assert.IsNull(c.DictionaryValueType); + } + [Test] public void DefaultContractResolverIgnoreIsSpecifiedTrue() { diff --git a/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs index 5ada7fa76..41c58138d 100644 --- a/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs +++ b/Src/Newtonsoft.Json.Tests/TestFixtureBase.cs @@ -212,11 +212,9 @@ protected string GetDataContractJsonSerializeResult(object o) public static string ResolvePath(string path) { -#if !DNXCORE50 - return Path.Combine(TestContext.CurrentContext.TestDirectory, path); -#else - return path; -#endif + var assemblyPath = Path.GetDirectoryName(typeof(TestFixtureBase).Assembly().Location); + + return Path.Combine(assemblyPath, path); } protected string GetOffset(DateTime d, DateFormatHandling dateFormatHandling) diff --git a/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs b/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs index 638039faf..3ac0020c4 100644 --- a/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs +++ b/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs @@ -25,6 +25,8 @@ using System; +#nullable disable + namespace Newtonsoft.Json.Bson { internal enum BsonBinaryType : byte diff --git a/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs b/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs index 815bbe11a..1f3c0aa3c 100644 --- a/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs @@ -29,6 +29,8 @@ using System.Text; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Bson { internal class BsonBinaryWriter diff --git a/Src/Newtonsoft.Json/Bson/BsonObjectId.cs b/Src/Newtonsoft.Json/Bson/BsonObjectId.cs index 4c57e7f90..4e1461d19 100644 --- a/Src/Newtonsoft.Json/Bson/BsonObjectId.cs +++ b/Src/Newtonsoft.Json/Bson/BsonObjectId.cs @@ -26,6 +26,8 @@ using System; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Bson { /// diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs index fe8a24811..45569331d 100644 --- a/Src/Newtonsoft.Json/Bson/BsonReader.cs +++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs @@ -32,6 +32,8 @@ using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Linq; +#nullable disable + namespace Newtonsoft.Json.Bson { /// diff --git a/Src/Newtonsoft.Json/Bson/BsonToken.cs b/Src/Newtonsoft.Json/Bson/BsonToken.cs index 631584c96..202bca6e5 100644 --- a/Src/Newtonsoft.Json/Bson/BsonToken.cs +++ b/Src/Newtonsoft.Json/Bson/BsonToken.cs @@ -26,6 +26,8 @@ using System.Collections; using System.Collections.Generic; +#nullable disable + namespace Newtonsoft.Json.Bson { internal abstract class BsonToken diff --git a/Src/Newtonsoft.Json/Bson/BsonType.cs b/Src/Newtonsoft.Json/Bson/BsonType.cs index e1192985c..fefae2c9b 100644 --- a/Src/Newtonsoft.Json/Bson/BsonType.cs +++ b/Src/Newtonsoft.Json/Bson/BsonType.cs @@ -23,6 +23,8 @@ // OTHER DEALINGS IN THE SOFTWARE. #endregion +#nullable disable + namespace Newtonsoft.Json.Bson { internal enum BsonType : sbyte diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index 3d1c0a15a..47d34fa3b 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -35,6 +35,8 @@ using Newtonsoft.Json.Linq; using System.Globalization; +#nullable disable + namespace Newtonsoft.Json.Bson { /// diff --git a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs index 83f0717b8..4dfc83278 100644 --- a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs @@ -51,7 +51,7 @@ public class BinaryConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -70,7 +70,7 @@ private byte[] GetByteArray(object value) if (value.GetType().FullName == BinaryTypeName) { EnsureReflectionObject(value.GetType()); - return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName); + return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName)!; } #endif #if HAVE_ADO_NET @@ -101,7 +101,7 @@ private static void EnsureReflectionObject(Type t) /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -123,7 +123,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { // current token is already at base64 string // unable to call ReadAsBytes so do it the old fashion way - string encodedData = reader.Value.ToString(); + string encodedData = reader.Value!.ToString(); data = Convert.FromBase64String(encodedData); } else @@ -140,7 +140,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { EnsureReflectionObject(t); - return _reflectionObject.Creator(data); + return _reflectionObject.Creator!(data); } #endif diff --git a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs index 5571c37f1..5f918de25 100644 --- a/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs @@ -28,6 +28,8 @@ using System.Globalization; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Converters { /// diff --git a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs index 8f54c0c62..f693ce574 100644 --- a/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs +++ b/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs @@ -41,7 +41,7 @@ public abstract class CustomCreationConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { throw new NotSupportedException("CustomCreationConverter should only be used while deserializing."); } @@ -54,7 +54,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { diff --git a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs index 7605f9c4e..61bb62536 100644 --- a/Src/Newtonsoft.Json/Converters/DataSetConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataSetConverter.cs @@ -41,7 +41,7 @@ public class DataSetConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -50,7 +50,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } DataSet dataSet = (DataSet)value; - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DataTableConverter converter = new DataTableConverter(); @@ -74,7 +74,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -92,10 +92,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist while (reader.TokenType == JsonToken.PropertyName) { - DataTable dt = ds.Tables[(string)reader.Value]; + DataTable dt = ds.Tables[(string)reader.Value!]; bool exists = (dt != null); - dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer); + dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer)!; if (!exists) { diff --git a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs index 5a7f6886b..7f8c529e4 100644 --- a/Src/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -45,7 +45,7 @@ public class DataTableConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -54,7 +54,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } DataTable table = (DataTable)value; - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartArray(); @@ -87,7 +87,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -106,7 +106,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist // populate the name from the property name if (reader.TokenType == JsonToken.PropertyName) { - dt.TableName = (string)reader.Value; + dt.TableName = (string)reader.Value!; reader.ReadAndAssert(); @@ -140,7 +140,7 @@ private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer se while (reader.TokenType == JsonToken.PropertyName) { - string columnName = (string)reader.Value; + string columnName = (string)reader.Value!; reader.ReadAndAssert(); @@ -177,7 +177,7 @@ private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer se reader.ReadAndAssert(); } - List o = new List(); + List o = new List(); while (reader.TokenType != JsonToken.EndArray) { @@ -218,7 +218,7 @@ private static Type GetColumnDataType(JsonReader reader) case JsonToken.String: case JsonToken.Date: case JsonToken.Bytes: - return reader.ValueType; + return reader.ValueType!; case JsonToken.Null: case JsonToken.Undefined: case JsonToken.EndArray: diff --git a/Src/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs b/Src/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs index d850db9c7..0d9afdf13 100644 --- a/Src/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs +++ b/Src/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs @@ -48,17 +48,32 @@ public class DiscriminatedUnionConverter : JsonConverter #region UnionDefinition internal class Union { - public List Cases; - public FSharpFunction TagReader { get; set; } + public readonly FSharpFunction TagReader; + public readonly List Cases; + + public Union(FSharpFunction tagReader, List cases) + { + TagReader = tagReader; + Cases = cases; + } } internal class UnionCase { - public int Tag; - public string Name; - public PropertyInfo[] Fields; - public FSharpFunction FieldReader; - public FSharpFunction Constructor; + public readonly int Tag; + public readonly string Name; + public readonly PropertyInfo[] Fields; + public readonly FSharpFunction FieldReader; + public readonly FSharpFunction Constructor; + + public UnionCase(int tag, string name, PropertyInfo[] fields, FSharpFunction fieldReader, FSharpFunction constructor) + { + Tag = tag; + Name = name; + Fields = fields; + FieldReader = fieldReader; + Constructor = constructor; + } } #endregion @@ -74,31 +89,28 @@ private static Type CreateUnionTypeLookup(Type t) // need to get declaring type to avoid duplicate Unions in cache // hacky but I can't find an API to get the declaring type without GetUnionCases - object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null); + object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null)!; object caseInfo = cases.First(); - Type unionType = (Type)FSharpUtils.GetUnionCaseInfoDeclaringType(caseInfo); + Type unionType = (Type)FSharpUtils.GetUnionCaseInfoDeclaringType(caseInfo)!; return unionType; } private static Union CreateUnion(Type t) { - Union u = new Union(); - - u.TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null); - u.Cases = new List(); + Union u = new Union((FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null), new List()); - object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null); + object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null)!; foreach (object unionCaseInfo in cases) { - UnionCase unionCase = new UnionCase(); - unionCase.Tag = (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo); - unionCase.Name = (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo); - unionCase.Fields = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo); - unionCase.FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null); - unionCase.Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null); + UnionCase unionCase = new UnionCase( + (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo), + (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo), + (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo)!, + (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null), + (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null)); u.Cases.Add(unionCase); } @@ -112,9 +124,15 @@ private static Union CreateUnion(Type t) /// 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, object? value, JsonSerializer serializer) { - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + if (value == null) + { + writer.WriteNull(); + return; + } + + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; Type unionType = UnionTypeLookupCache.Get(value.GetType()); Union union = UnionCache.Get(unionType); @@ -127,7 +145,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s writer.WriteValue(caseInfo.Name); if (caseInfo.Fields != null && caseInfo.Fields.Length > 0) { - object[] fields = (object[])caseInfo.FieldReader.Invoke(value); + object[] fields = (object[])caseInfo.FieldReader.Invoke(value)!; writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName); writer.WriteStartArray(); @@ -148,30 +166,30 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } - UnionCase caseInfo = null; - string caseName = null; - JArray fields = null; + UnionCase? caseInfo = null; + string? caseName = null; + JArray? fields = null; // start object reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase)) { reader.ReadAndAssert(); Union union = UnionCache.Get(objectType); - caseName = reader.Value.ToString(); + caseName = reader.Value!.ToString(); caseInfo = union.Cases.SingleOrDefault(c => c.Name == caseName); @@ -203,7 +221,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName)); } - object[] typedFieldValues = new object[caseInfo.Fields.Length]; + object?[] typedFieldValues = new object?[caseInfo.Fields.Length]; if (caseInfo.Fields.Length > 0 && fields == null) { diff --git a/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs b/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs index aeeb87a06..ed8c02106 100644 --- a/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs +++ b/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs @@ -50,16 +50,22 @@ public class EntityKeyMemberConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { + if (value == null) + { + writer.WriteNull(); + return; + } + EnsureReflectionObject(value.GetType()); - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; - string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName); - object keyValue = _reflectionObject.GetValue(value, ValuePropertyName); + string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName)!; + object? keyValue = _reflectionObject.GetValue(value, ValuePropertyName); - Type keyValueType = keyValue?.GetType(); + Type? keyValueType = keyValue?.GetType(); writer.WriteStartObject(); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName); @@ -71,7 +77,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s if (keyValueType != null) { - if (JsonSerializerInternalWriter.TryConvertToString(keyValue, keyValueType, out string valueJson)) + if (JsonSerializerInternalWriter.TryConvertToString(keyValue!, keyValueType, out string? valueJson)) { writer.WriteValue(valueJson); } @@ -92,7 +98,7 @@ private static void ReadAndAssertProperty(JsonReader reader, string propertyName { reader.ReadAndAssert(); - if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) + if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value?.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) { throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } @@ -106,19 +112,19 @@ private static void ReadAndAssertProperty(JsonReader reader, string propertyName /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { EnsureReflectionObject(objectType); - object entityKeyMember = _reflectionObject.Creator(); + object entityKeyMember = _reflectionObject.Creator!(); ReadAndAssertProperty(reader, KeyPropertyName); reader.ReadAndAssert(); - _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value.ToString()); + _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value?.ToString()); ReadAndAssertProperty(reader, TypePropertyName); reader.ReadAndAssert(); - string type = reader.Value.ToString(); + string? type = reader.Value?.ToString(); Type t = Type.GetType(type); diff --git a/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs b/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs index c946692b8..0b5153fd4 100644 --- a/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs +++ b/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs @@ -46,7 +46,7 @@ public class ExpandoObjectConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { // can write is set to false } @@ -59,12 +59,12 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return ReadValue(reader); } - private object ReadValue(JsonReader reader) + private object? ReadValue(JsonReader reader) { if (!reader.MoveToContent()) { @@ -89,7 +89,7 @@ private object ReadValue(JsonReader reader) private object ReadList(JsonReader reader) { - IList list = new List(); + IList list = new List(); while (reader.Read()) { @@ -98,7 +98,7 @@ private object ReadList(JsonReader reader) case JsonToken.Comment: break; default: - object v = ReadValue(reader); + object? v = ReadValue(reader); list.Add(v); break; @@ -112,21 +112,21 @@ private object ReadList(JsonReader reader) private object ReadObject(JsonReader reader) { - IDictionary expandoObject = new ExpandoObject(); + IDictionary expandoObject = new ExpandoObject(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } - object v = ReadValue(reader); + object? v = ReadValue(reader); expandoObject[propertyName] = v; break; diff --git a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs index 5a2e9322e..49977b5ed 100644 --- a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs @@ -37,8 +37,8 @@ public class IsoDateTimeConverter : DateTimeConverterBase private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; - private string _dateTimeFormat; - private CultureInfo _culture; + private string? _dateTimeFormat; + private CultureInfo? _culture; /// /// Gets or sets the date time styles used when converting a date to and from JSON. @@ -54,7 +54,7 @@ public DateTimeStyles DateTimeStyles /// Gets or sets the date time format used when converting a date to and from JSON. /// /// The date time format used when converting a date to and from JSON. - public string DateTimeFormat + public string? DateTimeFormat { get => _dateTimeFormat ?? string.Empty; set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; @@ -76,7 +76,7 @@ public CultureInfo Culture /// 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, object? value, JsonSerializer serializer) { string text; @@ -104,7 +104,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s #endif else { - throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value))); + throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)!)); } writer.WriteValue(text); @@ -118,7 +118,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool nullable = ReflectionUtils.IsNullableType(objectType); if (reader.TokenType == JsonToken.Null) @@ -142,7 +142,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist #if HAVE_DATE_TIME_OFFSET if (t == typeof(DateTimeOffset)) { - return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value); + return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value!); } // converter is expected to return a DateTime @@ -160,7 +160,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - string dateText = reader.Value.ToString(); + string? dateText = reader.Value?.ToString(); if (string.IsNullOrEmpty(dateText) && nullable) { diff --git a/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs index 24194b764..34082451f 100644 --- a/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs @@ -40,7 +40,7 @@ public class JavaScriptDateTimeConverter : DateTimeConverterBase /// 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, object? value, JsonSerializer serializer) { long ticks; @@ -74,7 +74,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -86,12 +86,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return null; } - if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal)) + if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); } - if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime d, out string errorMessage)) + if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime d, out string? errorMessage)) { throw JsonSerializationException.Create(reader, errorMessage); } diff --git a/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs b/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs index 2d4197032..0f12f1fab 100644 --- a/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs +++ b/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs @@ -56,11 +56,17 @@ private static ReflectionObject InitializeReflectionObject(Type t) /// 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, object? value, JsonSerializer serializer) { + if (value == null) + { + writer.WriteNull(); + return; + } + ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType()); - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName); @@ -78,7 +84,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -90,8 +96,8 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist return null; } - object key = null; - object value = null; + object? key = null; + object? value = null; reader.ReadAndAssert(); @@ -105,7 +111,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist while (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(keyContract, false); @@ -126,7 +132,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist reader.ReadAndAssert(); } - return reflectionObject.Creator(key, value); + return reflectionObject.Creator!(key, value); } /// diff --git a/Src/Newtonsoft.Json/Converters/RegexConverter.cs b/Src/Newtonsoft.Json/Converters/RegexConverter.cs index 719a06ad6..8bf6e9f9d 100644 --- a/Src/Newtonsoft.Json/Converters/RegexConverter.cs +++ b/Src/Newtonsoft.Json/Converters/RegexConverter.cs @@ -47,7 +47,7 @@ public class RegexConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -84,7 +84,7 @@ private void WriteBson(BsonWriter writer, Regex regex) // 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode // ('.' matches everything), and 'u' to make \w, \W, etc. match unicode. - string options = null; + string? options = null; if (HasFlag(regex.Options, RegexOptions.IgnoreCase)) { @@ -114,7 +114,7 @@ private void WriteBson(BsonWriter writer, Regex regex) private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer) { - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName); @@ -132,7 +132,7 @@ private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { switch (reader.TokenType) { @@ -149,7 +149,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist private object ReadRegexString(JsonReader reader) { - string regexText = (string)reader.Value; + string regexText = (string)reader.Value!; if (regexText.Length > 0 && regexText[0] == '/') { @@ -171,7 +171,7 @@ private object ReadRegexString(JsonReader reader) private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) { - string pattern = null; + string? pattern = null; RegexOptions? options = null; while (reader.Read()) @@ -179,7 +179,7 @@ private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) switch (reader.TokenType) { case JsonToken.PropertyName: - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (!reader.Read()) { @@ -188,7 +188,7 @@ private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase)) { - pattern = (string)reader.Value; + pattern = (string?)reader.Value; } else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase)) { diff --git a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs index 6639235e2..550c02d97 100644 --- a/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -82,7 +82,7 @@ public bool CamelCaseText /// Gets or sets the naming strategy used to resolve how enum text is written. /// /// The naming strategy used to resolve how enum text is written. - public NamingStrategy NamingStrategy { get; set; } + public NamingStrategy? NamingStrategy { get; set; } /// /// Gets or sets a value indicating whether integer values are allowed when serializing and deserializing. @@ -175,7 +175,7 @@ public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParam /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -185,7 +185,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s Enum e = (Enum)value; - if (!EnumUtils.TryToString(e.GetType(), value, NamingStrategy, out string enumName)) + if (!EnumUtils.TryToString(e.GetType(), value, NamingStrategy, out string? enumName)) { if (!AllowIntegerValues) { @@ -209,7 +209,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -228,14 +228,14 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { if (reader.TokenType == JsonToken.String) { - string enumText = reader.Value.ToString(); + string? enumText = reader.Value?.ToString(); - if (enumText == string.Empty && isNullable) + if (string.IsNullOrEmpty(enumText) && isNullable) { return null; } - return EnumUtils.ParseEnum(t, NamingStrategy, enumText, !AllowIntegerValues); + return EnumUtils.ParseEnum(t, NamingStrategy, enumText!, !AllowIntegerValues); } if (reader.TokenType == JsonToken.Integer) diff --git a/Src/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs index c5b03bb5c..d80be6edd 100644 --- a/Src/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs @@ -42,7 +42,7 @@ public class UnixDateTimeConverter : DateTimeConverterBase /// 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, object? value, JsonSerializer serializer) { long seconds; @@ -77,7 +77,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool nullable = ReflectionUtils.IsNullable(objectType); if (reader.TokenType == JsonToken.Null) @@ -94,11 +94,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist if (reader.TokenType == JsonToken.Integer) { - seconds = (long)reader.Value; + seconds = (long)reader.Value!; } else if (reader.TokenType == JsonToken.String) { - if (!long.TryParse((string)reader.Value, out seconds)) + if (!long.TryParse((string)reader.Value!, out seconds)) { throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } diff --git a/Src/Newtonsoft.Json/Converters/VersionConverter.cs b/Src/Newtonsoft.Json/Converters/VersionConverter.cs index df52718f1..e0cded265 100644 --- a/Src/Newtonsoft.Json/Converters/VersionConverter.cs +++ b/Src/Newtonsoft.Json/Converters/VersionConverter.cs @@ -40,7 +40,7 @@ public class VersionConverter : JsonConverter /// 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, object? value, JsonSerializer serializer) { if (value == null) { @@ -64,7 +64,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { @@ -76,7 +76,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { try { - Version v = new Version((string)reader.Value); + Version v = new Version((string)reader.Value!); return v; } catch (Exception ex) diff --git a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs index 6e7ba0597..c3205eced 100644 --- a/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -38,6 +38,7 @@ #endif using Newtonsoft.Json.Utilities; using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace Newtonsoft.Json.Converters { @@ -53,44 +54,44 @@ public XmlDocumentWrapper(XmlDocument document) _document = document; } - public IXmlNode CreateComment(string data) + public IXmlNode CreateComment(string? data) { return new XmlNodeWrapper(_document.CreateComment(data)); } - public IXmlNode CreateTextNode(string text) + public IXmlNode CreateTextNode(string? text) { return new XmlNodeWrapper(_document.CreateTextNode(text)); } - public IXmlNode CreateCDataSection(string data) + public IXmlNode CreateCDataSection(string? data) { return new XmlNodeWrapper(_document.CreateCDataSection(data)); } - public IXmlNode CreateWhitespace(string text) + public IXmlNode CreateWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateWhitespace(text)); } - public IXmlNode CreateSignificantWhitespace(string text) + public IXmlNode CreateSignificantWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); } - public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone) + public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) { return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); } #if HAVE_XML_DOCUMENT_TYPE - public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset) + public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) { return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); } #endif - public IXmlNode CreateProcessingInstruction(string target, string data) + public IXmlNode CreateProcessingInstruction(string target, string? data) { return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); } @@ -105,7 +106,7 @@ public IXmlElement CreateElement(string qualifiedName, string namespaceUri) return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri)); } - public IXmlNode CreateAttribute(string name, string value) + public IXmlNode CreateAttribute(string name, string? value) { XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name)); attribute.Value = value; @@ -113,7 +114,7 @@ public IXmlNode CreateAttribute(string name, string value) return attribute; } - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value) + public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) { XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)); attribute.Value = value; @@ -121,7 +122,7 @@ public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, strin return attribute; } - public IXmlElement DocumentElement + public IXmlElement? DocumentElement { get { @@ -149,7 +150,7 @@ public void SetAttributeNode(IXmlNode attribute) { XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute; - _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode); + _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode!); } public string GetPrefixOfNamespace(string namespaceUri) @@ -204,26 +205,26 @@ public XmlDocumentTypeWrapper(XmlDocumentType documentType) public string InternalSubset => _documentType.InternalSubset; - public override string LocalName => "DOCTYPE"; + public override string? LocalName => "DOCTYPE"; } #endif internal class XmlNodeWrapper : IXmlNode { private readonly XmlNode _node; - private List _childNodes; - private List _attributes; + private List? _childNodes; + private List? _attributes; public XmlNodeWrapper(XmlNode node) { _node = node; } - public object WrappedNode => _node; + public object? WrappedNode => _node; public XmlNodeType NodeType => _node.NodeType; - public virtual string LocalName => _node.LocalName; + public virtual string? LocalName => _node.LocalName; public List ChildNodes { @@ -309,7 +310,7 @@ private bool HasAttributes } } - public IXmlNode ParentNode + public IXmlNode? ParentNode { get { @@ -324,7 +325,7 @@ public IXmlNode ParentNode } } - public string Value + public string? Value { get => _node.Value; set => _node.Value = value; @@ -340,7 +341,7 @@ public IXmlNode AppendChild(IXmlNode newChild) return newChild; } - public string NamespaceUri => _node.NamespaceURI; + public string? NamespaceUri => _node.NamespaceURI; } #endif #endregion @@ -348,22 +349,22 @@ public IXmlNode AppendChild(IXmlNode newChild) #region Interfaces internal interface IXmlDocument : IXmlNode { - IXmlNode CreateComment(string text); - IXmlNode CreateTextNode(string text); - IXmlNode CreateCDataSection(string data); - IXmlNode CreateWhitespace(string text); - IXmlNode CreateSignificantWhitespace(string text); - IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone); + IXmlNode CreateComment(string? text); + IXmlNode CreateTextNode(string? text); + IXmlNode CreateCDataSection(string? data); + IXmlNode CreateWhitespace(string? text); + IXmlNode CreateSignificantWhitespace(string? text); + IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone); #if HAVE_XML_DOCUMENT_TYPE - IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset); + IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset); #endif - IXmlNode CreateProcessingInstruction(string target, string data); + IXmlNode CreateProcessingInstruction(string target, string? data); IXmlElement CreateElement(string elementName); IXmlElement CreateElement(string qualifiedName, string namespaceUri); - IXmlNode CreateAttribute(string name, string value); - IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value); + IXmlNode CreateAttribute(string name, string? value); + IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value); - IXmlElement DocumentElement { get; } + IXmlElement? DocumentElement { get; } } internal interface IXmlDeclaration : IXmlNode @@ -391,14 +392,14 @@ internal interface IXmlElement : IXmlNode internal interface IXmlNode { XmlNodeType NodeType { get; } - string LocalName { get; } + string? LocalName { get; } List ChildNodes { get; } List Attributes { get; } - IXmlNode ParentNode { get; } - string Value { get; set; } + IXmlNode? ParentNode { get; } + string? Value { get; set; } IXmlNode AppendChild(IXmlNode newChild); - string NamespaceUri { get; } - object WrappedNode { get; } + string? NamespaceUri { get; } + object? WrappedNode { get; } } #endregion @@ -449,12 +450,12 @@ public XDocumentTypeWrapper(XDocumentType documentType) public string InternalSubset => _documentType.InternalSubset; - public override string LocalName => "DOCTYPE"; + public override string? LocalName => "DOCTYPE"; } internal class XDocumentWrapper : XContainerWrapper, IXmlDocument { - private XDocument Document => (XDocument)WrappedNode; + private XDocument Document => (XDocument)WrappedNode!; public XDocumentWrapper(XDocument document) : base(document) @@ -488,42 +489,42 @@ protected override bool HasChildNodes } } - public IXmlNode CreateComment(string text) + public IXmlNode CreateComment(string? text) { return new XObjectWrapper(new XComment(text)); } - public IXmlNode CreateTextNode(string text) + public IXmlNode CreateTextNode(string? text) { return new XObjectWrapper(new XText(text)); } - public IXmlNode CreateCDataSection(string data) + public IXmlNode CreateCDataSection(string? data) { return new XObjectWrapper(new XCData(data)); } - public IXmlNode CreateWhitespace(string text) + public IXmlNode CreateWhitespace(string? text) { return new XObjectWrapper(new XText(text)); } - public IXmlNode CreateSignificantWhitespace(string text) + public IXmlNode CreateSignificantWhitespace(string? text) { return new XObjectWrapper(new XText(text)); } - public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone) + public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) { return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); } - public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset) + public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) { return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); } - public IXmlNode CreateProcessingInstruction(string target, string data) + public IXmlNode CreateProcessingInstruction(string target, string? data) { return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); } @@ -539,18 +540,18 @@ public IXmlElement CreateElement(string qualifiedName, string namespaceUri) return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri))); } - public IXmlNode CreateAttribute(string name, string value) + public IXmlNode CreateAttribute(string name, string? value) { return new XAttributeWrapper(new XAttribute(name, value)); } - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value) + public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) { string localName = MiscellaneousUtils.GetLocalName(qualifiedName); return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value)); } - public IXmlElement DocumentElement + public IXmlElement? DocumentElement { get { @@ -579,20 +580,20 @@ public override IXmlNode AppendChild(IXmlNode newChild) internal class XTextWrapper : XObjectWrapper { - private XText Text => (XText)WrappedNode; + private XText Text => (XText)WrappedNode!; public XTextWrapper(XText text) : base(text) { } - public override string Value + public override string? Value { get => Text.Value; set => Text.Value = value; } - public override IXmlNode ParentNode + public override IXmlNode? ParentNode { get { @@ -608,20 +609,20 @@ public override IXmlNode ParentNode internal class XCommentWrapper : XObjectWrapper { - private XComment Text => (XComment)WrappedNode; + private XComment Text => (XComment)WrappedNode!; public XCommentWrapper(XComment text) : base(text) { } - public override string Value + public override string? Value { get => Text.Value; set => Text.Value = value; } - public override IXmlNode ParentNode + public override IXmlNode? ParentNode { get { @@ -637,16 +638,16 @@ public override IXmlNode ParentNode internal class XProcessingInstructionWrapper : XObjectWrapper { - private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)WrappedNode; + private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)WrappedNode!; public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction) : base(processingInstruction) { } - public override string LocalName => ProcessingInstruction.Target; + public override string? LocalName => ProcessingInstruction.Target; - public override string Value + public override string? Value { get => ProcessingInstruction.Data; set => ProcessingInstruction.Data = value; @@ -655,9 +656,9 @@ public override string Value internal class XContainerWrapper : XObjectWrapper { - private List _childNodes; + private List? _childNodes; - private XContainer Container => (XContainer)WrappedNode; + private XContainer Container => (XContainer)WrappedNode!; public XContainerWrapper(XContainer container) : base(container) @@ -692,7 +693,7 @@ public override List ChildNodes protected virtual bool HasChildNodes => Container.LastNode != null; - public override IXmlNode ParentNode + public override IXmlNode? ParentNode { get { @@ -761,26 +762,26 @@ public override IXmlNode AppendChild(IXmlNode newChild) internal class XObjectWrapper : IXmlNode { - private readonly XObject _xmlObject; + private readonly XObject? _xmlObject; - public XObjectWrapper(XObject xmlObject) + public XObjectWrapper(XObject? xmlObject) { _xmlObject = xmlObject; } - public object WrappedNode => _xmlObject; + public object? WrappedNode => _xmlObject; - public virtual XmlNodeType NodeType => _xmlObject.NodeType; + public virtual XmlNodeType NodeType => _xmlObject?.NodeType ?? XmlNodeType.None; - public virtual string LocalName => null; + public virtual string? LocalName => null; public virtual List ChildNodes => XmlNodeConverter.EmptyChildNodes; public virtual List Attributes => XmlNodeConverter.EmptyChildNodes; - public virtual IXmlNode ParentNode => null; + public virtual IXmlNode? ParentNode => null; - public virtual string Value + public virtual string? Value { get => null; set => throw new InvalidOperationException(); @@ -791,29 +792,29 @@ public virtual IXmlNode AppendChild(IXmlNode newChild) throw new InvalidOperationException(); } - public virtual string NamespaceUri => null; + public virtual string? NamespaceUri => null; } internal class XAttributeWrapper : XObjectWrapper { - private XAttribute Attribute => (XAttribute)WrappedNode; + private XAttribute Attribute => (XAttribute)WrappedNode!; public XAttributeWrapper(XAttribute attribute) : base(attribute) { } - public override string Value + public override string? Value { get => Attribute.Value; set => Attribute.Value = value; } - public override string LocalName => Attribute.Name.LocalName; + public override string? LocalName => Attribute.Name.LocalName; - public override string NamespaceUri => Attribute.Name.NamespaceName; + public override string? NamespaceUri => Attribute.Name.NamespaceName; - public override IXmlNode ParentNode + public override IXmlNode? ParentNode { get { @@ -829,9 +830,9 @@ public override IXmlNode ParentNode internal class XElementWrapper : XContainerWrapper, IXmlElement { - private List _attributes; + private List? _attributes; - private XElement Element => (XElement)WrappedNode; + private XElement Element => (XElement)WrappedNode!; public XElementWrapper(XElement element) : base(element) @@ -853,7 +854,7 @@ public override List Attributes // cache results to prevent multiple reads which kills perf in large documents if (_attributes == null) { - if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri)) + if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri!)) { _attributes = XmlNodeConverter.EmptyChildNodes; } @@ -867,7 +868,7 @@ public override List Attributes // ensure elements created with a namespace but no namespace attribute are converted correctly // e.g. new XElement("{http://example.com}MyElement"); - string namespaceUri = NamespaceUri; + string namespaceUri = NamespaceUri!; if (HasImplicitNamespaceAttribute(namespaceUri)) { _attributes.Insert(0, new XAttributeWrapper(new XAttribute("xmlns", namespaceUri))); @@ -915,15 +916,15 @@ public override IXmlNode AppendChild(IXmlNode newChild) return result; } - public override string Value + public override string? Value { get => Element.Value; set => Element.Value = value; } - public override string LocalName => Element.Name.LocalName; + public override string? LocalName => Element.Name.LocalName; - public override string NamespaceUri => Element.Name.NamespaceName; + public override string? NamespaceUri => Element.Name.NamespaceName; public string GetPrefixOfNamespace(string namespaceUri) { @@ -954,7 +955,7 @@ public class XmlNodeConverter : JsonConverter /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements. /// /// The name of the deserialized root element. - public string DeserializeRootElementName { get; set; } + public string? DeserializeRootElementName { get; set; } /// /// Gets or sets a value to indicate whether to write the Json.NET array attribute. @@ -985,7 +986,7 @@ public class XmlNodeConverter : JsonConverter /// The to write to. /// The calling serializer. /// The value. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { @@ -1031,9 +1032,9 @@ private IXmlNode WrapXml(object value) private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) { - List parentElements = null; + List? parentElements = null; - IXmlNode parent = node; + IXmlNode? parent = node; while ((parent = parent.ParentNode) != null) { if (parent.NodeType == XmlNodeType.Element) @@ -1067,7 +1068,7 @@ private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) { - string prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) + string? prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) ? null : manager.LookupPrefix(node.NamespaceUri); @@ -1160,9 +1161,9 @@ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespac // value of dictionary will be a single IXmlNode when there is one for a name, // or a List when there are multiple - Dictionary nodesGroupedByName = null; + Dictionary? nodesGroupedByName = null; - string nodeName = null; + string? nodeName = null; for (int i = 0; i < node.ChildNodes.Count; i++) { @@ -1208,7 +1209,7 @@ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespac { if (!(value is List nodes)) { - nodes = new List {(IXmlNode)value}; + nodes = new List {(IXmlNode)value!}; nodesGroupedByName[currentNodeName] = nodes; } @@ -1219,7 +1220,7 @@ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespac if (nodesGroupedByName == null) { - WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName); + WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName!); } else { @@ -1315,7 +1316,11 @@ private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager string namespacePrefix = (attribute.LocalName != "xmlns") ? XmlConvert.DecodeName(attribute.LocalName) : string.Empty; - string namespaceUri = attribute.Value; + string? namespaceUri = attribute.Value; + if (namespaceUri == null) + { + throw new JsonSerializationException("Namespace attribute must have a value."); + } manager.AddNamespace(namespacePrefix, namespaceUri); } @@ -1473,7 +1478,7 @@ private static bool AllSameName(IXmlNode node) /// 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 object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { switch (reader.TokenType) { @@ -1486,8 +1491,8 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist } XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); - IXmlDocument document = null; - IXmlNode rootNode = null; + IXmlDocument? document = null; + IXmlNode? rootNode = null; #if HAVE_XLINQ if (typeof(XObject).IsAssignableFrom(objectType)) @@ -1545,7 +1550,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist #if HAVE_XLINQ if (objectType == typeof(XElement)) { - XElement element = (XElement)document.DocumentElement.WrappedNode; + XElement element = (XElement)document.DocumentElement!.WrappedNode!; element.Remove(); return element; @@ -1554,7 +1559,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist #if HAVE_XML_DOCUMENT if (objectType == typeof(XmlElement)) { - return document.DocumentElement.WrappedNode; + return document.DocumentElement!.WrappedNode; } #endif @@ -1616,8 +1621,8 @@ private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode curr throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML."); } - Dictionary attributeNameValues = null; - string elementPrefix = null; + Dictionary? attributeNameValues = null; + string? elementPrefix = null; if (!EncodeSpecialCharacters) { @@ -1629,7 +1634,7 @@ private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode curr if (propertyName.StartsWith('@')) { string attributeName = propertyName.Substring(1); - string attributePrefix = MiscellaneousUtils.GetPrefix(attributeName); + string? attributePrefix = MiscellaneousUtils.GetPrefix(attributeName); AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); return; @@ -1666,7 +1671,7 @@ private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode curr CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); } - private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string elementPrefix, Dictionary attributeNameValues) + private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string? elementPrefix, Dictionary? attributeNameValues) { IXmlElement element = CreateElement(elementName, document, elementPrefix, manager); @@ -1675,10 +1680,10 @@ private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode cu if (attributeNameValues != null) { // add attributes to newly created element - foreach (KeyValuePair nameValue in attributeNameValues) + foreach (KeyValuePair nameValue in attributeNameValues) { string encodedName = XmlConvert.EncodeName(nameValue.Key); - string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key); + string? attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key); IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value) : document.CreateAttribute(encodedName, nameValue.Value); @@ -1694,7 +1699,7 @@ private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode cu case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: - string text = ConvertTokenToXmlValue(reader); + string? text = ConvertTokenToXmlValue(reader); if (text != null) { element.AppendChild(document.CreateTextNode(text)); @@ -1718,7 +1723,7 @@ private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode cu } } - private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string attributePrefix) + private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string? attributePrefix) { if (currentNode.NodeType == XmlNodeType.Document) { @@ -1726,7 +1731,7 @@ private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlN } string encodedName = XmlConvert.EncodeName(attributeName); - string attributeValue = ConvertTokenToXmlValue(reader); + string? attributeValue = ConvertTokenToXmlValue(reader); IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix), attributeValue) @@ -1735,7 +1740,7 @@ private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlN ((IXmlElement)currentNode).SetAttributeNode(attribute); } - private static string ConvertTokenToXmlValue(JsonReader reader) + private static string? ConvertTokenToXmlValue(JsonReader reader) { switch (reader.TokenType) { @@ -1782,7 +1787,7 @@ private static string ConvertTokenToXmlValue(JsonReader reader) #endif } case JsonToken.Bytes: - return Convert.ToBase64String((byte[])reader.Value); + return Convert.ToBase64String((byte[])reader.Value!); case JsonToken.Null: return null; default: @@ -1792,7 +1797,7 @@ private static string ConvertTokenToXmlValue(JsonReader reader) private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager) { - string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); + string? elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager); @@ -1858,9 +1863,9 @@ private bool ShouldReadInto(JsonReader reader) return true; } - private Dictionary ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) + private Dictionary? ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) { - Dictionary attributeNameValues = null; + Dictionary? attributeNameValues = null; bool finished = false; // read properties until first non-attribute is encountered @@ -1869,19 +1874,19 @@ private Dictionary ReadAttributeElements(JsonReader reader, XmlN switch (reader.TokenType) { case JsonToken.PropertyName: - string attributeName = reader.Value.ToString(); + string attributeName = reader.Value!.ToString(); if (!string.IsNullOrEmpty(attributeName)) { char firstChar = attributeName[0]; - string attributeValue; + string? attributeValue; switch (firstChar) { case '@': if (attributeNameValues == null) { - attributeNameValues = new Dictionary(); + attributeNameValues = new Dictionary(); } attributeName = attributeName.Substring(1); @@ -1889,7 +1894,7 @@ private Dictionary ReadAttributeElements(JsonReader reader, XmlN attributeValue = ConvertTokenToXmlValue(reader); attributeNameValues.Add(attributeName, attributeValue); - if (IsNamespaceAttribute(attributeName, out string namespacePrefix)) + if (IsNamespaceAttribute(attributeName, out string? namespacePrefix)) { manager.AddNamespace(namespacePrefix, attributeValue); } @@ -1909,7 +1914,7 @@ private Dictionary ReadAttributeElements(JsonReader reader, XmlN { if (attributeNameValues == null) { - attributeNameValues = new Dictionary(); + attributeNameValues = new Dictionary(); } // ensure that the prefix used is free @@ -1941,7 +1946,7 @@ private Dictionary ReadAttributeElements(JsonReader reader, XmlN if (attributeNameValues == null) { - attributeNameValues = new Dictionary(); + attributeNameValues = new Dictionary(); } attributeValue = reader.Value?.ToString(); @@ -1979,12 +1984,12 @@ private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNod { if (propertyName == DeclarationName) { - string version = null; - string encoding = null; - string standalone = null; + string? version = null; + string? encoding = null; + string? standalone = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { - switch (reader.Value.ToString()) + switch (reader.Value?.ToString()) { case "@version": reader.ReadAndAssert(); @@ -2016,13 +2021,13 @@ private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNod #if HAVE_XML_DOCUMENT_TYPE private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode) { - string name = null; - string publicId = null; - string systemId = null; - string internalSubset = null; + string? name = null; + string? publicId = null; + string? systemId = null; + string? internalSubset = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { - switch (reader.Value.ToString()) + switch (reader.Value?.ToString()) { case "@name": reader.ReadAndAssert(); @@ -2050,7 +2055,7 @@ private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNo } #endif - private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager) + private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) { string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName); string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); @@ -2072,7 +2077,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); } - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartArray) @@ -2086,7 +2091,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp if (count == 1 && WriteArrayAttribute) { - MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string elementPrefix, out string localName); + MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string? elementPrefix, out string localName); string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); foreach (IXmlNode childNode in currentNode.ChildNodes) @@ -2105,7 +2110,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp } continue; case JsonToken.StartConstructor: - string constructorName = reader.Value.ToString(); + string constructorName = reader.Value!.ToString(); while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) { @@ -2113,7 +2118,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp } break; case JsonToken.Comment: - currentNode.AppendChild(document.CreateComment((string)reader.Value)); + currentNode.AppendChild(document.CreateComment((string)reader.Value!)); break; case JsonToken.EndObject: case JsonToken.EndArray: @@ -2131,7 +2136,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp /// Attribute name to test. /// The attribute name prefix if it has one, otherwise an empty string. /// true if attribute name is for a namespace attribute, otherwise false. - private bool IsNamespaceAttribute(string attributeName, out string prefix) + private bool IsNamespaceAttribute(string attributeName, [NotNullWhen(true)]out string? prefix) { if (attributeName.StartsWith("xmlns", StringComparison.Ordinal)) { diff --git a/Src/Newtonsoft.Json/DefaultJsonNameTable.cs b/Src/Newtonsoft.Json/DefaultJsonNameTable.cs index 8b6db5522..5243160ea 100644 --- a/Src/Newtonsoft.Json/DefaultJsonNameTable.cs +++ b/Src/Newtonsoft.Json/DefaultJsonNameTable.cs @@ -59,7 +59,7 @@ public DefaultJsonNameTable() /// The zero-based index into the array specifying the first character of the name. /// The number of characters in the name. /// A string containing the same characters as the specified range of characters in the given array. - public override string Get(char[] key, int start, int length) + public override string? Get(char[] key, int start, int length) { if (length == 0) { diff --git a/Src/Newtonsoft.Json/IArrayPool.cs b/Src/Newtonsoft.Json/IArrayPool.cs index 15717f05a..361ee890b 100644 --- a/Src/Newtonsoft.Json/IArrayPool.cs +++ b/Src/Newtonsoft.Json/IArrayPool.cs @@ -17,6 +17,6 @@ public interface IArrayPool /// Return an array to the pool. /// /// The array that is being returned. - void Return(T[] array); + void Return(T[]? array); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/JsonContainerAttribute.cs b/Src/Newtonsoft.Json/JsonContainerAttribute.cs index e5ef292d3..28f35f531 100644 --- a/Src/Newtonsoft.Json/JsonContainerAttribute.cs +++ b/Src/Newtonsoft.Json/JsonContainerAttribute.cs @@ -38,25 +38,25 @@ public abstract class JsonContainerAttribute : Attribute /// Gets or sets the id. /// /// The id. - public string Id { get; set; } + public string? Id { get; set; } /// /// Gets or sets the title. /// /// The title. - public string Title { get; set; } + public string? Title { get; set; } /// /// Gets or sets the description. /// /// The description. - public string Description { get; set; } + public string? Description { get; set; } /// /// Gets or sets the collection's items converter. /// /// The collection's items converter. - public Type ItemConverterType { get; set; } + public Type? ItemConverterType { get; set; } /// /// The parameter list to use when constructing the described by . @@ -69,13 +69,13 @@ public abstract class JsonContainerAttribute : Attribute /// [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] /// /// - public object[] ItemConverterParameters { get; set; } + public object[]? ItemConverterParameters { get; set; } /// /// Gets or sets the of the . /// /// The of the . - public Type NamingStrategyType + public Type? NamingStrategyType { get => _namingStrategyType; set @@ -96,7 +96,7 @@ public Type NamingStrategyType /// [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] /// /// - public object[] NamingStrategyParameters + public object[]? NamingStrategyParameters { get => _namingStrategyParameters; set @@ -106,7 +106,7 @@ public object[] NamingStrategyParameters } } - internal NamingStrategy NamingStrategyInstance { get; set; } + internal NamingStrategy? NamingStrategyInstance { get; set; } // yuck. can't set nullable properties on an attribute in C# // have to use this approach to get an unset default state @@ -114,8 +114,8 @@ public object[] NamingStrategyParameters internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; - private Type _namingStrategyType; - private object[] _namingStrategyParameters; + private Type? _namingStrategyType; + private object[]? _namingStrategyParameters; /// /// Gets or sets a value that indicates whether to preserve object references. diff --git a/Src/Newtonsoft.Json/JsonConvert.cs b/Src/Newtonsoft.Json/JsonConvert.cs index b0e480d62..b09dc1ac5 100644 --- a/Src/Newtonsoft.Json/JsonConvert.cs +++ b/Src/Newtonsoft.Json/JsonConvert.cs @@ -36,9 +36,10 @@ using Newtonsoft.Json.Serialization; using System.Text; using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if HAVE_XLINQ using System.Xml.Linq; - #endif namespace Newtonsoft.Json @@ -395,7 +396,7 @@ internal static string ToString(TimeSpan value, char quoteChar) /// /// The value to convert. /// A JSON string representation of the . - public static string ToString(Uri value) + public static string ToString(Uri? value) { if (value == null) { @@ -415,7 +416,7 @@ internal static string ToString(Uri value, char quoteChar) /// /// The value to convert. /// A JSON string representation of the . - public static string ToString(string value) + public static string ToString(string? value) { return ToString(value, '"'); } @@ -426,7 +427,7 @@ public static string ToString(string value) /// The value to convert. /// The string delimiter character. /// A JSON string representation of the . - public static string ToString(string value, char delimiter) + public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } @@ -438,7 +439,7 @@ public static string ToString(string value, char delimiter) /// The string delimiter character. /// The string escape handling. /// A JSON string representation of the . - public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling) + public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { @@ -453,7 +454,7 @@ public static string ToString(string value, char delimiter, StringEscapeHandling /// /// The value to convert. /// A JSON string representation of the . - public static string ToString(object value) + public static string ToString(object? value) { if (value == null) { @@ -524,9 +525,9 @@ public static string ToString(object value) /// The object to serialize. /// A JSON string representation of the object. [DebuggerStepThrough] - public static string SerializeObject(object value) + public static string SerializeObject(object? value) { - return SerializeObject(value, null, (JsonSerializerSettings)null); + return SerializeObject(value, null, (JsonSerializerSettings?)null); } /// @@ -538,9 +539,9 @@ public static string SerializeObject(object value) /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object value, Formatting formatting) + public static string SerializeObject(object? value, Formatting formatting) { - return SerializeObject(value, formatting, (JsonSerializerSettings)null); + return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } /// @@ -550,9 +551,9 @@ public static string SerializeObject(object value, Formatting formatting) /// A collection of converters used while serializing. /// A JSON string representation of the object. [DebuggerStepThrough] - public static string SerializeObject(object value, params JsonConverter[] converters) + public static string SerializeObject(object? value, params JsonConverter[] converters) { - JsonSerializerSettings settings = (converters != null && converters.Length > 0) + JsonSerializerSettings? settings = (converters != null && converters.Length > 0) ? new JsonSerializerSettings { Converters = converters } : null; @@ -567,9 +568,9 @@ public static string SerializeObject(object value, params JsonConverter[] conver /// A collection of converters used while serializing. /// A JSON string representation of the object. [DebuggerStepThrough] - public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters) + public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { - JsonSerializerSettings settings = (converters != null && converters.Length > 0) + JsonSerializerSettings? settings = (converters != null && converters.Length > 0) ? new JsonSerializerSettings { Converters = converters } : null; @@ -586,7 +587,7 @@ public static string SerializeObject(object value, Formatting formatting, params /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object value, JsonSerializerSettings settings) + public static string SerializeObject(object? value, JsonSerializerSettings settings) { return SerializeObject(value, null, settings); } @@ -606,7 +607,7 @@ public static string SerializeObject(object value, JsonSerializerSettings settin /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object value, Type type, JsonSerializerSettings settings) + public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); @@ -624,7 +625,7 @@ public static string SerializeObject(object value, Type type, JsonSerializerSett /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings) + public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } @@ -645,7 +646,7 @@ public static string SerializeObject(object value, Formatting formatting, JsonSe /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings) + public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; @@ -653,7 +654,7 @@ public static string SerializeObject(object value, Type type, Formatting formatt return SerializeObjectInternal(value, type, jsonSerializer); } - private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer) + private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringBuilder sb = new StringBuilder(256); StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture); @@ -675,9 +676,9 @@ private static string SerializeObjectInternal(object value, Type type, JsonSeria /// The JSON to deserialize. /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static object DeserializeObject(string value) + public static object? DeserializeObject(string value) { - return DeserializeObject(value, null, (JsonSerializerSettings)null); + return DeserializeObject(value, null, (JsonSerializerSettings?)null); } /// @@ -690,7 +691,7 @@ public static object DeserializeObject(string value) /// /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static object DeserializeObject(string value, JsonSerializerSettings settings) + public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } @@ -702,9 +703,9 @@ public static object DeserializeObject(string value, JsonSerializerSettings sett /// The of object being deserialized. /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static object DeserializeObject(string value, Type type) + public static object? DeserializeObject(string value, Type type) { - return DeserializeObject(value, type, (JsonSerializerSettings)null); + return DeserializeObject(value, type, (JsonSerializerSettings?)null); } /// @@ -716,7 +717,7 @@ public static object DeserializeObject(string value, Type type) [DebuggerStepThrough] public static T DeserializeObject(string value) { - return DeserializeObject(value, (JsonSerializerSettings)null); + return DeserializeObject(value, (JsonSerializerSettings?)null); } /// @@ -765,9 +766,12 @@ public static T DeserializeAnonymousType(string value, T anonymousTypeObject, /// Converters to use while deserializing. /// The deserialized object from the JSON string. [DebuggerStepThrough] + [return: MaybeNull] public static T DeserializeObject(string value, params JsonConverter[] converters) { +#pragma warning disable CS8601 // Possible null reference assignment. return (T)DeserializeObject(value, typeof(T), converters); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -781,9 +785,12 @@ public static T DeserializeObject(string value, params JsonConverter[] conver /// /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static T DeserializeObject(string value, JsonSerializerSettings settings) + [return: MaybeNull] + public static T DeserializeObject(string value, JsonSerializerSettings? settings) { +#pragma warning disable CS8601 // Possible null reference assignment. return (T)DeserializeObject(value, typeof(T), settings); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -794,9 +801,9 @@ public static T DeserializeObject(string value, JsonSerializerSettings settin /// Converters to use while deserializing. /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static object DeserializeObject(string value, Type type, params JsonConverter[] converters) + public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { - JsonSerializerSettings settings = (converters != null && converters.Length > 0) + JsonSerializerSettings? settings = (converters != null && converters.Length > 0) ? new JsonSerializerSettings { Converters = converters } : null; @@ -813,7 +820,7 @@ public static object DeserializeObject(string value, Type type, params JsonConve /// If this is null, default serialization settings will be used. /// /// The deserialized object from the JSON string. - public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings) + public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, nameof(value)); @@ -853,7 +860,7 @@ public static void PopulateObject(string value, object target) /// The used to deserialize the object. /// If this is null, default serialization settings will be used. /// - public static void PopulateObject(string value, object target, JsonSerializerSettings settings) + public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); @@ -882,7 +889,7 @@ public static void PopulateObject(string value, object target, JsonSerializerSet /// /// The node to serialize. /// A JSON string of the . - public static string SerializeXmlNode(XmlNode node) + public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } @@ -893,7 +900,7 @@ public static string SerializeXmlNode(XmlNode node) /// The node to serialize. /// Indicates how the output should be formatted. /// A JSON string of the . - public static string SerializeXmlNode(XmlNode node, Formatting formatting) + public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter converter = new XmlNodeConverter(); @@ -907,7 +914,7 @@ public static string SerializeXmlNode(XmlNode node, Formatting formatting) /// Indicates how the output should be formatted. /// Omits writing the root object. /// A JSON string of the . - public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject) + public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; @@ -919,7 +926,7 @@ public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool /// /// The JSON string. /// The deserialized . - public static XmlDocument DeserializeXmlNode(string value) + public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } @@ -930,7 +937,7 @@ public static XmlDocument DeserializeXmlNode(string value) /// The JSON string. /// The name of the root element to append when deserializing. /// The deserialized . - public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName) + public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, false); } @@ -946,7 +953,7 @@ public static XmlDocument DeserializeXmlNode(string value, string deserializeRoo /// This attribute helps preserve arrays when converting the written XML back to JSON. /// /// The deserialized . - public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute) + public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, false); } @@ -968,14 +975,14 @@ public static XmlDocument DeserializeXmlNode(string value, string deserializeRoo /// as part of the XML element name. /// /// The deserialized . - public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) + public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter converter = new XmlNodeConverter(); converter.DeserializeRootElementName = deserializeRootElementName; converter.WriteArrayAttribute = writeArrayAttribute; converter.EncodeSpecialCharacters = encodeSpecialCharacters; - return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter); + return (XmlDocument?)DeserializeObject(value, typeof(XmlDocument), converter); } #endif @@ -985,7 +992,7 @@ public static XmlDocument DeserializeXmlNode(string value, string deserializeRoo /// /// The node to convert to JSON. /// A JSON string of the . - public static string SerializeXNode(XObject node) + public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } @@ -996,7 +1003,7 @@ public static string SerializeXNode(XObject node) /// The node to convert to JSON. /// Indicates how the output should be formatted. /// A JSON string of the . - public static string SerializeXNode(XObject node, Formatting formatting) + public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, false); } @@ -1008,7 +1015,7 @@ public static string SerializeXNode(XObject node, Formatting formatting) /// Indicates how the output should be formatted. /// Omits writing the root object. /// A JSON string of the . - public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject) + public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; @@ -1020,7 +1027,7 @@ public static string SerializeXNode(XObject node, Formatting formatting, bool om /// /// The JSON string. /// The deserialized . - public static XDocument DeserializeXNode(string value) + public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } @@ -1031,7 +1038,7 @@ public static XDocument DeserializeXNode(string value) /// The JSON string. /// The name of the root element to append when deserializing. /// The deserialized . - public static XDocument DeserializeXNode(string value, string deserializeRootElementName) + public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, false); } @@ -1047,7 +1054,7 @@ public static XDocument DeserializeXNode(string value, string deserializeRootEle /// This attribute helps preserve arrays when converting the written XML back to JSON. /// /// The deserialized . - public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute) + public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, false); } @@ -1069,14 +1076,14 @@ public static XDocument DeserializeXNode(string value, string deserializeRootEle /// as part of the XML element name. /// /// The deserialized . - public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) + public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter converter = new XmlNodeConverter(); converter.DeserializeRootElementName = deserializeRootElementName; converter.WriteArrayAttribute = writeArrayAttribute; converter.EncodeSpecialCharacters = encodeSpecialCharacters; - return (XDocument)DeserializeObject(value, typeof(XDocument), converter); + return (XDocument?)DeserializeObject(value, typeof(XDocument), converter); } #endif #endregion diff --git a/Src/Newtonsoft.Json/JsonConverter.cs b/Src/Newtonsoft.Json/JsonConverter.cs index 2ac14e50f..5e75103ee 100644 --- a/Src/Newtonsoft.Json/JsonConverter.cs +++ b/Src/Newtonsoft.Json/JsonConverter.cs @@ -26,6 +26,8 @@ using System; using Newtonsoft.Json.Utilities; using System.Globalization; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace Newtonsoft.Json { @@ -40,7 +42,7 @@ public abstract class JsonConverter /// The to write to. /// The value. /// The calling serializer. - public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer); + public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); /// /// Reads the JSON representation of the object. @@ -50,7 +52,7 @@ public abstract class JsonConverter /// The existing value of object being read. /// The calling serializer. /// The object value. - public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer); + public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); /// /// Determines whether this instance can convert the specified object type. @@ -86,13 +88,15 @@ public abstract class JsonConverter : JsonConverter /// The to write to. /// The value. /// The calling serializer. - public sealed override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!(value != null ? value is T : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } +#pragma warning disable CS8601 // Possible null reference assignment. WriteJson(writer, (T)value, serializer); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -101,7 +105,7 @@ public sealed override void WriteJson(JsonWriter writer, object value, JsonSeria /// The to write to. /// The value. /// The calling serializer. - public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer); + public abstract void WriteJson(JsonWriter writer, [AllowNull]T value, JsonSerializer serializer); /// /// Reads the JSON representation of the object. @@ -111,14 +115,16 @@ public sealed override void WriteJson(JsonWriter writer, object value, JsonSeria /// The existing value of object being read. /// The calling serializer. /// The object value. - public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool existingIsNull = existingValue == null; if (!(existingIsNull || existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } +#pragma warning disable CS8601 // Possible null reference assignment. return ReadJson(reader, objectType, existingIsNull ? default : (T)existingValue, !existingIsNull, serializer); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -130,7 +136,7 @@ public sealed override object ReadJson(JsonReader reader, Type objectType, objec /// The existing value has a value. /// The calling serializer. /// The object value. - public abstract T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer); + public abstract T ReadJson(JsonReader reader, Type objectType, [AllowNull]T existingValue, bool hasExistingValue, JsonSerializer serializer); /// /// Determines whether this instance can convert the specified object type. diff --git a/Src/Newtonsoft.Json/JsonConverterAttribute.cs b/Src/Newtonsoft.Json/JsonConverterAttribute.cs index 2c09128c1..a5f071ea7 100644 --- a/Src/Newtonsoft.Json/JsonConverterAttribute.cs +++ b/Src/Newtonsoft.Json/JsonConverterAttribute.cs @@ -47,7 +47,7 @@ public sealed class JsonConverterAttribute : Attribute /// The parameter list to use when constructing the described by . /// If null, the default constructor is used. /// - public object[] ConverterParameters { get; } + public object[]? ConverterParameters { get; } /// /// Initializes a new instance of the class. diff --git a/Src/Newtonsoft.Json/JsonException.cs b/Src/Newtonsoft.Json/JsonException.cs index a5fb5775a..603a78162 100644 --- a/Src/Newtonsoft.Json/JsonException.cs +++ b/Src/Newtonsoft.Json/JsonException.cs @@ -63,7 +63,7 @@ public JsonException(string message) /// /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception, or null if no inner exception is specified. - public JsonException(string message, Exception innerException) + public JsonException(string message, Exception? innerException) : base(message, innerException) { } diff --git a/Src/Newtonsoft.Json/JsonNameTable.cs b/Src/Newtonsoft.Json/JsonNameTable.cs index b7937618a..1f2d243a6 100644 --- a/Src/Newtonsoft.Json/JsonNameTable.cs +++ b/Src/Newtonsoft.Json/JsonNameTable.cs @@ -12,6 +12,6 @@ public abstract class JsonNameTable /// The zero-based index into the array specifying the first character of the name. /// The number of characters in the name. /// A string containing the same characters as the specified range of characters in the given array. - public abstract string Get(char[] key, int start, int length); + public abstract string? Get(char[] key, int start, int length); } } diff --git a/Src/Newtonsoft.Json/JsonPosition.cs b/Src/Newtonsoft.Json/JsonPosition.cs index b301993ea..92a62344d 100644 --- a/Src/Newtonsoft.Json/JsonPosition.cs +++ b/Src/Newtonsoft.Json/JsonPosition.cs @@ -46,7 +46,7 @@ internal struct JsonPosition internal JsonContainerType Type; internal int Position; - internal string PropertyName; + internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) @@ -62,7 +62,7 @@ internal int CalculateLength() switch (Type) { case JsonContainerType.Object: - return PropertyName.Length + 5; + return PropertyName!.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; @@ -71,12 +71,12 @@ internal int CalculateLength() } } - internal void WriteTo(StringBuilder sb, ref StringWriter writer, ref char[] buffer) + internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: - string propertyName = PropertyName; + string propertyName = PropertyName!; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append(@"['"); @@ -130,8 +130,8 @@ internal static string BuildPath(List positions, JsonPosition? cur } StringBuilder sb = new StringBuilder(capacity); - StringWriter writer = null; - char[] buffer = null; + StringWriter? writer = null; + char[]? buffer = null; if (positions != null) { foreach (JsonPosition state in positions) @@ -147,7 +147,7 @@ internal static string BuildPath(List positions, JsonPosition? cur return sb.ToString(); } - internal static string FormatMessage(IJsonLineInfo lineInfo, string path, string message) + internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { // don't add a fullstop and space when message ends with a new line if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) diff --git a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs index ec6532faf..7ad05382e 100644 --- a/Src/Newtonsoft.Json/JsonPropertyAttribute.cs +++ b/Src/Newtonsoft.Json/JsonPropertyAttribute.cs @@ -52,7 +52,7 @@ public sealed class JsonPropertyAttribute : Attribute /// Gets or sets the type used when serializing the property's collection items. /// /// The collection's items type. - public Type ItemConverterType { get; set; } + public Type? ItemConverterType { get; set; } /// /// The parameter list to use when constructing the described by . @@ -65,13 +65,13 @@ public sealed class JsonPropertyAttribute : Attribute /// [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] /// /// - public object[] ItemConverterParameters { get; set; } + public object[]? ItemConverterParameters { get; set; } /// /// Gets or sets the of the . /// /// The of the . - public Type NamingStrategyType { get; set; } + public Type? NamingStrategyType { get; set; } /// /// The parameter list to use when constructing the described by . @@ -84,7 +84,7 @@ public sealed class JsonPropertyAttribute : Attribute /// [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] /// /// - public object[] NamingStrategyParameters { get; set; } + public object[]? NamingStrategyParameters { get; set; } /// /// Gets or sets the null value handling used when serializing this property. @@ -172,7 +172,7 @@ public Required Required /// Gets or sets the name of the property. /// /// The name of the property. - public string PropertyName { get; set; } + public string? PropertyName { get; set; } /// /// Gets or sets the reference loop handling used when serializing the property's collection items. diff --git a/Src/Newtonsoft.Json/JsonReader.Async.cs b/Src/Newtonsoft.Json/JsonReader.Async.cs index e61e933ae..024903e76 100644 --- a/Src/Newtonsoft.Json/JsonReader.Async.cs +++ b/Src/Newtonsoft.Json/JsonReader.Async.cs @@ -101,12 +101,12 @@ internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken /// property returns the []. This result will be null at the end of an array. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsBytesAsync(CancellationToken cancellationToken = default) + public virtual Task ReadAsBytesAsync(CancellationToken cancellationToken = default) { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBytes()); + return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBytes()); } - internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) + internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List buffer = new List(); @@ -199,9 +199,9 @@ internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancel /// property returns the . This result will be null at the end of an array. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task ReadAsStringAsync(CancellationToken cancellationToken = default) + public virtual Task ReadAsStringAsync(CancellationToken cancellationToken = default) { - return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsString()); + return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsString()); } internal async Task ReadAndMoveToContentAsync(CancellationToken cancellationToken) diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index f827c278c..ba19d3d3e 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -113,18 +113,18 @@ protected internal enum State // current Token data private JsonToken _tokenType; - private object _value; + private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; - private CultureInfo _culture; + private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; - private string _dateFormatString; - private List _stack; + private string? _dateFormatString; + private List? _stack; /// /// Gets the current reader state. @@ -219,7 +219,7 @@ public FloatParseHandling FloatParseHandling /// /// Gets or sets how custom date formatted strings are parsed when reading JSON. /// - public string DateFormatString + public string? DateFormatString { get => _dateFormatString; set => _dateFormatString = value; @@ -250,12 +250,12 @@ public int? MaxDepth /// /// Gets the text value of the current JSON token. /// - public virtual object Value => _value; + public virtual object? Value => _value; /// /// Gets the .NET type for the current JSON token. /// - public virtual Type ValueType => _value?.GetType(); + public virtual Type? ValueType => _value?.GetType(); /// /// Gets the depth of the current token in the JSON document. @@ -295,7 +295,7 @@ public virtual string Path JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null; - return JsonPosition.BuildPath(_stack, current); + return JsonPosition.BuildPath(_stack!, current); } } @@ -408,7 +408,7 @@ private JsonContainerType Peek() return null; case JsonToken.Integer: case JsonToken.Float: - object v = Value; + object v = Value!; if (v is int i) { return i; @@ -436,14 +436,14 @@ private JsonContainerType Peek() SetToken(JsonToken.Integer, i, false); return i; case JsonToken.String: - string s = (string)Value; + string? s = (string?)Value; return ReadInt32String(s); } throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); } - internal int? ReadInt32String(string s) + internal int? ReadInt32String(string? s) { if (string.IsNullOrEmpty(s)) { @@ -467,7 +467,7 @@ private JsonContainerType Peek() /// Reads the next JSON token from the source as a . /// /// A . This method will return null at the end of an array. - public virtual string ReadAsString() + public virtual string? ReadAsString() { JsonToken t = GetContentToken(); @@ -478,12 +478,12 @@ public virtual string ReadAsString() case JsonToken.EndArray: return null; case JsonToken.String: - return (string)Value; + return (string?)Value; } if (JsonTokenUtils.IsPrimitiveToken(t)) { - object v = Value; + object? v = Value; if (v != null) { string s; @@ -508,7 +508,7 @@ public virtual string ReadAsString() /// Reads the next JSON token from the source as a []. /// /// A [] or null if the next JSON token is null. This method will return null at the end of an array. - public virtual byte[] ReadAsBytes() + public virtual byte[]? ReadAsBytes() { JsonToken t = GetContentToken(); @@ -518,7 +518,7 @@ public virtual byte[] ReadAsBytes() { ReadIntoWrappedTypeObject(); - byte[] data = ReadAsBytes(); + byte[]? data = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) @@ -533,7 +533,7 @@ public virtual byte[] ReadAsBytes() { // attempt to convert possible base 64 or GUID string to bytes // GUID has to have format 00000000-0000-0000-0000-000000000000 - string s = (string)Value; + string s = (string)Value!; byte[] data; @@ -565,7 +565,7 @@ public virtual byte[] ReadAsBytes() return data; } - return (byte[])Value; + return (byte[]?)Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); } @@ -627,7 +627,7 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) return null; case JsonToken.Integer: case JsonToken.Float: - object v = Value; + object v = Value!; if (v is double d) { return d; @@ -648,13 +648,13 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) return (double)d; case JsonToken.String: - return ReadDoubleString((string)Value); + return ReadDoubleString((string?)Value); } throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); } - internal double? ReadDoubleString(string s) + internal double? ReadDoubleString(string? s) { if (string.IsNullOrEmpty(s)) { @@ -705,15 +705,15 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) SetToken(JsonToken.Boolean, b, false); return b; case JsonToken.String: - return ReadBooleanString((string)Value); + return ReadBooleanString((string?)Value); case JsonToken.Boolean: - return (bool)Value; + return (bool)Value!; } throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); } - internal bool? ReadBooleanString(string s) + internal bool? ReadBooleanString(string? s) { if (string.IsNullOrEmpty(s)) { @@ -749,7 +749,7 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) return null; case JsonToken.Integer: case JsonToken.Float: - object v = Value; + object v = Value!; if (v is decimal d) { @@ -778,13 +778,13 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) SetToken(JsonToken.Float, d, false); return d; case JsonToken.String: - return ReadDecimalString((string)Value); + return ReadDecimalString((string?)Value); } throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); } - internal decimal? ReadDecimalString(string s) + internal decimal? ReadDecimalString(string? s) { if (string.IsNullOrEmpty(s)) { @@ -830,16 +830,15 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) } #endif - return (DateTime)Value; + return (DateTime)Value!; case JsonToken.String: - string s = (string)Value; - return ReadDateTimeString(s); + return ReadDateTimeString((string?)Value); } throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } - internal DateTime? ReadDateTimeString(string s) + internal DateTime? ReadDateTimeString(string? s) { if (string.IsNullOrEmpty(s)) { @@ -885,16 +884,16 @@ private bool ReadArrayElementIntoByteArrayReportDone(List buffer) SetToken(JsonToken.Date, new DateTimeOffset(time), false); } - return (DateTimeOffset)Value; + return (DateTimeOffset)Value!; case JsonToken.String: - string s = (string)Value; + string? s = (string?)Value; return ReadDateTimeOffsetString(s); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); } } - internal DateTimeOffset? ReadDateTimeOffsetString(string s) + internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (string.IsNullOrEmpty(s)) { @@ -985,7 +984,7 @@ protected void SetToken(JsonToken newToken) /// /// The new token. /// The value. - protected void SetToken(JsonToken newToken, object value) + protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, true); } @@ -996,7 +995,7 @@ protected void SetToken(JsonToken newToken, object value) /// The new token. /// The value. /// A flag indicating whether the position index inside an array should be updated. - protected void SetToken(JsonToken newToken, object value, bool updateIndex) + protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; @@ -1027,7 +1026,7 @@ protected void SetToken(JsonToken newToken, object value, bool updateIndex) case JsonToken.PropertyName: _currentState = State.Property; - _currentPosition.PropertyName = (string)value; + _currentPosition.PropertyName = (string)value!; break; case JsonToken.Undefined: case JsonToken.Integer: @@ -1170,7 +1169,7 @@ internal void ReadAndAssert() } } - internal void ReadForTypeAndAssert(JsonContract contract, bool hasConverter) + internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { @@ -1178,7 +1177,7 @@ internal void ReadForTypeAndAssert(JsonContract contract, bool hasConverter) } } - internal bool ReadForType(JsonContract contract, bool hasConverter) + internal bool ReadForType(JsonContract? contract, bool hasConverter) { // don't read properties with converters as a specific value // the value might be a string which will then get converted which will error if read as date for example diff --git a/Src/Newtonsoft.Json/JsonReaderException.cs b/Src/Newtonsoft.Json/JsonReaderException.cs index f73107ba2..bcf9a5004 100644 --- a/Src/Newtonsoft.Json/JsonReaderException.cs +++ b/Src/Newtonsoft.Json/JsonReaderException.cs @@ -54,7 +54,7 @@ public class JsonReaderException : JsonException /// Gets the path to the JSON where the error occurred. /// /// The path to the JSON where the error occurred. - public string Path { get; } + public string? Path { get; } /// /// Initializes a new instance of the class. @@ -107,7 +107,7 @@ public JsonReaderException(SerializationInfo info, StreamingContext context) /// The line number indicating where the error occurred. /// The line position indicating where the error occurred. /// The exception that is the cause of the current exception, or null if no inner exception is specified. - public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception innerException) + public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; @@ -120,12 +120,12 @@ internal static JsonReaderException Create(JsonReader reader, string message) return Create(reader, message, null); } - internal static JsonReaderException Create(JsonReader reader, string message, Exception ex) + internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } - internal static JsonReaderException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex) + internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); diff --git a/Src/Newtonsoft.Json/JsonSerializationException.cs b/Src/Newtonsoft.Json/JsonSerializationException.cs index 308b799bb..a54789a76 100644 --- a/Src/Newtonsoft.Json/JsonSerializationException.cs +++ b/Src/Newtonsoft.Json/JsonSerializationException.cs @@ -54,7 +54,7 @@ public class JsonSerializationException : JsonException /// Gets the path to the JSON where the error occurred. /// /// The path to the JSON where the error occurred. - public string Path { get; } + public string? Path { get; } /// /// Initializes a new instance of the class. @@ -107,7 +107,7 @@ public JsonSerializationException(SerializationInfo info, StreamingContext conte /// The line number indicating where the error occurred. /// The line position indicating where the error occurred. /// The exception that is the cause of the current exception, or null if no inner exception is specified. - public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception innerException) + public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; @@ -120,12 +120,12 @@ internal static JsonSerializationException Create(JsonReader reader, string mess return Create(reader, message, null); } - internal static JsonSerializationException Create(JsonReader reader, string message, Exception ex) + internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } - internal static JsonSerializationException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex) + internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); diff --git a/Src/Newtonsoft.Json/JsonSerializer.cs b/Src/Newtonsoft.Json/JsonSerializer.cs index d3e1d5ec0..9370c1079 100644 --- a/Src/Newtonsoft.Json/JsonSerializer.cs +++ b/Src/Newtonsoft.Json/JsonSerializer.cs @@ -35,6 +35,8 @@ using Newtonsoft.Json.Utilities; using System.Runtime.Serialization; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace Newtonsoft.Json { @@ -54,13 +56,13 @@ public class JsonSerializer internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; - internal JsonConverterCollection _converters; + internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; - internal ITraceWriter _traceWriter; - internal IEqualityComparer _equalityComparer; + internal ITraceWriter? _traceWriter; + internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; - private IReferenceResolver _referenceResolver; + private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; @@ -73,7 +75,7 @@ public class JsonSerializer private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; - private string _dateFormatString; + private string? _dateFormatString; private bool _dateFormatStringSet; /// @@ -84,7 +86,7 @@ public class JsonSerializer /// /// Gets or sets the used by the serializer when resolving references. /// - public virtual IReferenceResolver ReferenceResolver + public virtual IReferenceResolver? ReferenceResolver { get => GetReferenceResolver(); set @@ -106,11 +108,6 @@ public virtual SerializationBinder Binder { get { - if (_serializationBinder == null) - { - return null; - } - if (_serializationBinder is SerializationBinder legacySerializationBinder) { return legacySerializationBinder; @@ -155,7 +152,7 @@ public virtual ISerializationBinder SerializationBinder /// Gets or sets the used by the serializer when writing trace messages. /// /// The trace writer. - public virtual ITraceWriter TraceWriter + public virtual ITraceWriter? TraceWriter { get => _traceWriter; set => _traceWriter = value; @@ -165,7 +162,7 @@ public virtual ITraceWriter TraceWriter /// Gets or sets the equality comparer used by the serializer when comparing references. /// /// The equality comparer. - public virtual IEqualityComparer EqualityComparer + public virtual IEqualityComparer? EqualityComparer { get => _equalityComparer; set => _equalityComparer = value; @@ -599,7 +596,7 @@ public static JsonSerializer Create() /// The will not use default settings /// from . /// - public static JsonSerializer Create(JsonSerializerSettings settings) + public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer serializer = Create(); @@ -624,7 +621,7 @@ public static JsonSerializer Create(JsonSerializerSettings settings) public static JsonSerializer CreateDefault() { // copy static to local variable to avoid concurrency issues - JsonSerializerSettings defaultSettings = JsonConvert.DefaultSettings?.Invoke(); + JsonSerializerSettings? defaultSettings = JsonConvert.DefaultSettings?.Invoke(); return Create(defaultSettings); } @@ -640,7 +637,7 @@ public static JsonSerializer CreateDefault() /// The will use default settings /// from as well as the specified . /// - public static JsonSerializer CreateDefault(JsonSerializerSettings settings) + public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer serializer = CreateDefault(); if (settings != null) @@ -814,14 +811,14 @@ internal virtual void PopulateInternal(JsonReader reader, object target) SetupReader( reader, - out CultureInfo previousCulture, + out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, - out string previousDateFormatString); + out string? previousDateFormatString); - TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) + TraceJsonReader? traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null; @@ -830,7 +827,7 @@ internal virtual void PopulateInternal(JsonReader reader, object target) if (traceJsonReader != null) { - TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); + TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); @@ -842,7 +839,7 @@ internal virtual void PopulateInternal(JsonReader reader, object target) /// The that contains the JSON structure to deserialize. /// The being deserialized. [DebuggerStepThrough] - public object Deserialize(JsonReader reader) + public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } @@ -855,7 +852,7 @@ public object Deserialize(JsonReader reader) /// The of object being deserialized. /// The instance of being deserialized. [DebuggerStepThrough] - public object Deserialize(TextReader reader, Type objectType) + public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } @@ -868,9 +865,12 @@ public object Deserialize(TextReader reader, Type objectType) /// The type of the object to deserialize. /// The instance of being deserialized. [DebuggerStepThrough] + [return: MaybeNull] public T Deserialize(JsonReader reader) { +#pragma warning disable CS8601 // Possible null reference assignment. return (T)Deserialize(reader, typeof(T)); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -881,34 +881,34 @@ public T Deserialize(JsonReader reader) /// The of object being deserialized. /// The instance of being deserialized. [DebuggerStepThrough] - public object Deserialize(JsonReader reader, Type objectType) + public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } - internal virtual object DeserializeInternal(JsonReader reader, Type objectType) + internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); SetupReader( reader, - out CultureInfo previousCulture, + out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, - out string previousDateFormatString); + out string? previousDateFormatString); - TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) + TraceJsonReader? traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null; JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this); - object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); + object? value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { - TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); + TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); @@ -916,7 +916,7 @@ internal virtual object DeserializeInternal(JsonReader reader, Type objectType) return value; } - private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString) + private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { @@ -987,7 +987,7 @@ private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out } } - private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string previousDateFormatString) + private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { // reset reader back to previous options if (previousCulture != null) @@ -1028,7 +1028,7 @@ private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTim /// /// The used to write the JSON structure. /// The to serialize. - public void Serialize(TextWriter textWriter, object value) + public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } @@ -1044,7 +1044,7 @@ public void Serialize(TextWriter textWriter, object value) /// This parameter is used when is to write out the type name if the type of the value does not match. /// Specifying the type is optional. /// - public void Serialize(JsonWriter jsonWriter, object value, Type objectType) + public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } @@ -1060,7 +1060,7 @@ public void Serialize(JsonWriter jsonWriter, object value, Type objectType) /// This parameter is used when is Auto to write out the type name if the type of the value does not match. /// Specifying the type is optional. /// - public void Serialize(TextWriter textWriter, object value, Type objectType) + public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } @@ -1071,7 +1071,7 @@ public void Serialize(TextWriter textWriter, object value, Type objectType) /// /// The used to write the JSON structure. /// The to serialize. - public void Serialize(JsonWriter jsonWriter, object value) + public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } @@ -1087,7 +1087,7 @@ private TraceJsonReader CreateTraceJsonReader(JsonReader reader) return traceReader; } - internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType) + internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, nameof(jsonWriter)); @@ -1127,21 +1127,21 @@ internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Typ jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } - CultureInfo previousCulture = null; + CultureInfo? previousCulture = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { previousCulture = jsonWriter.Culture; jsonWriter.Culture = _culture; } - string previousDateFormatString = null; + string? previousDateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { previousDateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } - TraceJsonWriter traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) + TraceJsonWriter? traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null; @@ -1150,7 +1150,7 @@ internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Typ if (traceJsonWriter != null) { - TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); + TraceWriter!.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } // reset writer back to previous options @@ -1194,12 +1194,12 @@ internal IReferenceResolver GetReferenceResolver() return _referenceResolver; } - internal JsonConverter GetMatchingConverter(Type type) + internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } - internal static JsonConverter GetMatchingConverter(IList converters, Type objectType) + internal static JsonConverter? GetMatchingConverter(IList? converters, Type objectType) { #if DEBUG ValidationUtils.ArgumentNotNull(objectType, nameof(objectType)); diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs index ea68dc948..fa924c738 100644 --- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs @@ -69,11 +69,11 @@ public class JsonSerializerSettings internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; - internal CultureInfo _culture; + internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; - internal string _dateFormatString; + internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; @@ -225,27 +225,27 @@ public ConstructorHandling ConstructorHandling /// serializing .NET objects to JSON and vice versa. /// /// The contract resolver. - public IContractResolver ContractResolver { get; set; } + public IContractResolver? ContractResolver { get; set; } /// /// Gets or sets the equality comparer used by the serializer when comparing references. /// /// The equality comparer. - public IEqualityComparer EqualityComparer { get; set; } + public IEqualityComparer? EqualityComparer { get; set; } /// /// Gets or sets the used by the serializer when resolving references. /// /// The reference resolver. [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] - public IReferenceResolver ReferenceResolver + public IReferenceResolver? ReferenceResolver { get => ReferenceResolverProvider?.Invoke(); set { ReferenceResolverProvider = (value != null) ? () => value - : (Func)null; + : (Func?)null; } } @@ -253,20 +253,20 @@ public IReferenceResolver ReferenceResolver /// 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; } + public Func? ReferenceResolverProvider { get; set; } /// /// Gets or sets the used by the serializer when writing trace messages. /// /// The trace writer. - public ITraceWriter TraceWriter { get; set; } + public ITraceWriter? TraceWriter { get; set; } /// /// Gets or sets the used by the serializer when resolving type names. /// /// The binder. [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] - public SerializationBinder Binder + public SerializationBinder? Binder { get { @@ -289,13 +289,13 @@ public SerializationBinder Binder /// Gets or sets the used by the serializer when resolving type names. /// /// The binder. - public ISerializationBinder SerializationBinder { get; set; } + public ISerializationBinder? SerializationBinder { get; set; } /// /// Gets or sets the error handler called during serialization and deserialization. /// /// The error handler called during serialization and deserialization. - public EventHandler Error { get; set; } + public EventHandler? Error { get; set; } /// /// Gets or sets the used by the serializer when invoking serialization callback methods. diff --git a/Src/Newtonsoft.Json/JsonTextReader.Async.cs b/Src/Newtonsoft.Json/JsonTextReader.Async.cs index bb18359a7..443c3055b 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.Async.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.Async.cs @@ -34,6 +34,7 @@ using System.Threading.Tasks; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; +using System.Diagnostics; namespace Newtonsoft.Json { @@ -110,6 +111,8 @@ private async Task DoReadAsync(Task task, CancellationToken cancella private async Task ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -193,6 +196,8 @@ private async Task ParsePostValueAsync(bool ignoreComments, CancellationTo private async Task ReadFromFinishedAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); @@ -222,6 +227,8 @@ private Task ReadDataAsync(bool append, CancellationToken cancellationToken private async Task ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + if (_isEndOfFile) { return 0; @@ -244,6 +251,8 @@ private async Task ReadDataAsync(bool append, int charsRequired, Cancellati private async Task ParseValueAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -373,6 +382,8 @@ private async Task ParseValueAsync(CancellationToken cancellationToken) private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + int charPos = _charPos; int initialPosition = _charPos; int lastWritePosition = _charPos; @@ -589,6 +600,8 @@ private async Task ReadCharsAsync(int relativePosition, bool append, Cance private async Task ParseObjectAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -646,6 +659,8 @@ private async Task ParseObjectAsync(CancellationToken cancellationToken) private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + // should have already parsed / character before reaching this method _charPos++; @@ -742,6 +757,8 @@ private async Task ParseCommentAsync(bool setToken, CancellationToken cancellati private async Task EatWhitespaceAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -798,6 +815,8 @@ private async Task MatchValueAsync(string value, CancellationToken cancell private async Task MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + // will match value and then move to the next character, checking that it is a separator character if (!await MatchValueAsync(value, cancellationToken).ConfigureAwait(false)) { @@ -812,7 +831,7 @@ private async Task MatchValueWithTrailingSeparatorAsync(string value, Canc return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0'; } - private async Task MatchAndSetAsync(string value, JsonToken newToken, object tokenValue, CancellationToken cancellationToken) + private async Task MatchAndSetAsync(string value, JsonToken newToken, object? tokenValue, CancellationToken cancellationToken) { if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(false)) { @@ -841,6 +860,8 @@ private Task ParseNullAsync(CancellationToken cancellationToken) private async Task ParseConstructorAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); @@ -939,6 +960,8 @@ private async Task ParseNumberNegativeInfinityAsync(ReadType readType, C private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; @@ -956,6 +979,8 @@ private Task ParseUndefinedAsync(CancellationToken cancellationToken) private async Task ParsePropertyAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + char firstChar = _chars[_charPos]; char quoteChar; @@ -1008,6 +1033,8 @@ private async Task ParsePropertyAsync(CancellationToken cancellationToken) private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + int charPos = _charPos; while (true) @@ -1042,6 +1069,8 @@ private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + int initialPosition = _charPos; // parse unquoted property name until whitespace or colon @@ -1091,6 +1120,8 @@ private async Task ReadNullCharAsync(CancellationToken cancellationToken) private async Task HandleNullAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false)) { if (_chars[_charPos + 1] == 'u') @@ -1109,6 +1140,8 @@ private async Task HandleNullAsync(CancellationToken cancellationToken) private async Task ReadFinishedAsync(CancellationToken cancellationToken) { + Debug.Assert(_chars != null); + if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); @@ -1131,9 +1164,10 @@ private async Task ReadFinishedAsync(CancellationToken cancellationToken) SetToken(JsonToken.None); } - private async Task ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) + private async Task ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -1266,9 +1300,10 @@ private async Task ReadStringValueAsync(ReadType readType, CancellationT } } - private async Task ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) + private async Task ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -1395,6 +1430,7 @@ private async Task ReadNumberValueAsync(ReadType readType, CancellationT internal async Task DoReadAsBooleanAsync(CancellationToken cancellationToken) { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -1522,14 +1558,16 @@ private async Task ReadNumberValueAsync(ReadType readType, CancellationT /// property returns the []. This result will be null at the end of an array. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task ReadAsBytesAsync(CancellationToken cancellationToken = default) + public override Task ReadAsBytesAsync(CancellationToken cancellationToken = default) { return _safeAsync ? DoReadAsBytesAsync(cancellationToken) : base.ReadAsBytesAsync(cancellationToken); } - internal async Task DoReadAsBytesAsync(CancellationToken cancellationToken) + internal async Task DoReadAsBytesAsync(CancellationToken cancellationToken) { EnsureBuffer(); + Debug.Assert(_chars != null); + bool isWrapped = false; switch (_currentState) @@ -1563,7 +1601,7 @@ internal async Task DoReadAsBytesAsync(CancellationToken cancellationTok case '"': case '\'': await ParseStringAsync(currentChar, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(false); - byte[] data = (byte[])Value; + byte[]? data = (byte[]?)Value; if (isWrapped) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); @@ -1753,14 +1791,14 @@ private async Task ReadIntoWrappedTypeObjectAsync(CancellationToken cancellation /// property returns the . This result will be null at the end of an array. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task ReadAsStringAsync(CancellationToken cancellationToken = default) + public override Task ReadAsStringAsync(CancellationToken cancellationToken = default) { return _safeAsync ? DoReadAsStringAsync(cancellationToken) : base.ReadAsStringAsync(cancellationToken); } - internal async Task DoReadAsStringAsync(CancellationToken cancellationToken) + internal async Task DoReadAsStringAsync(CancellationToken cancellationToken) { - return (string)await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false); + return (string?)await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false); } } } diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 1783da400..b95cb8216 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -27,6 +27,7 @@ using System.Runtime.CompilerServices; using System.IO; using System.Globalization; +using System.Diagnostics; #if HAVE_BIG_INTEGER using System.Numerics; #endif @@ -66,7 +67,7 @@ public partial class JsonTextReader : JsonReader, IJsonLineInfo #endif private readonly TextReader _reader; - private char[] _chars; + private char[]? _chars; private int _charsUsed; private int _charPos; private int _lineStartPos; @@ -74,7 +75,7 @@ public partial class JsonTextReader : JsonReader, IJsonLineInfo private bool _isEndOfFile; private StringBuffer _stringBuffer; private StringReference _stringReference; - private IArrayPool _arrayPool; + private IArrayPool? _arrayPool; /// /// Initializes a new instance of the class with the specified . @@ -96,7 +97,7 @@ public JsonTextReader(TextReader reader) } #if DEBUG - internal char[] CharBuffer + internal char[]? CharBuffer { get => _chars; set => _chars = value; @@ -108,12 +109,12 @@ internal char[] CharBuffer /// /// Gets or sets the reader's property name table. /// - public JsonNameTable PropertyNameTable { get; set; } + public JsonNameTable? PropertyNameTable { get; set; } /// /// Gets or sets the reader's character buffer pool. /// - public IArrayPool ArrayPool + public IArrayPool? ArrayPool { get => _arrayPool; set @@ -137,6 +138,8 @@ private void EnsureBufferNotEmpty() private void SetNewLine(bool hasNextChar) { + Debug.Assert(_chars != null); + if (hasNextChar && _chars[_charPos] == StringUtils.LineFeed) { _charPos++; @@ -249,6 +252,8 @@ private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int ds private void ShiftBufferIfNeeded() { + Debug.Assert(_chars != null); + // once in the last 10% of the buffer, or buffer is already very large then // shift the remaining content to the start to avoid unnecessarily increasing // the buffer size when reading numbers/strings @@ -275,6 +280,8 @@ private int ReadData(bool append) private void PrepareBufferForReadData(bool append, int charsRequired) { + Debug.Assert(_chars != null); + // char buffer is full if (_charsUsed + charsRequired >= _chars.Length - 1) { @@ -338,6 +345,7 @@ private int ReadData(bool append, int charsRequired) } PrepareBufferForReadData(append, charsRequired); + Debug.Assert(_chars != null); int attemptCharReadCount = _chars.Length - _charsUsed - 1; @@ -406,6 +414,7 @@ private bool ReadChars(int relativePosition, bool append) public override bool Read() { EnsureBuffer(); + Debug.Assert(_chars != null); while (true) { @@ -476,18 +485,20 @@ public override bool Read() /// Reads the next JSON token from the underlying as a . /// /// A . This method will return null at the end of an array. - public override string ReadAsString() + public override string? ReadAsString() { - return (string)ReadStringValue(ReadType.ReadAsString); + return (string?)ReadStringValue(ReadType.ReadAsString); } /// /// Reads the next JSON token from the underlying as a []. /// /// A [] or null if the next JSON token is null. This method will return null at the end of an array. - public override byte[] ReadAsBytes() + public override byte[]? ReadAsBytes() { EnsureBuffer(); + Debug.Assert(_chars != null); + bool isWrapped = false; switch (_currentState) @@ -520,7 +531,7 @@ public override byte[] ReadAsBytes() case '"': case '\'': ParseString(currentChar, ReadType.ReadAsBytes); - byte[] data = (byte[])Value; + byte[]? data = (byte[]?)Value; if (isWrapped) { ReaderReadAndAssert(); @@ -589,9 +600,10 @@ public override byte[] ReadAsBytes() } } - private object ReadStringValue(ReadType readType) + private object? ReadStringValue(ReadType readType) { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -718,7 +730,7 @@ private object ReadStringValue(ReadType readType) } } - private object FinishReadQuotedStringValue(ReadType readType) + private object? FinishReadQuotedStringValue(ReadType readType) { switch (readType) { @@ -731,7 +743,7 @@ private object FinishReadQuotedStringValue(ReadType readType) return time; } - return ReadDateTimeString((string)Value); + return ReadDateTimeString((string?)Value); #if HAVE_DATE_TIME_OFFSET case ReadType.ReadAsDateTimeOffset: if (Value is DateTimeOffset offset) @@ -739,7 +751,7 @@ private object FinishReadQuotedStringValue(ReadType readType) return offset; } - return ReadDateTimeOffsetString((string)Value); + return ReadDateTimeOffsetString((string?)Value); #endif default: throw new ArgumentOutOfRangeException(nameof(readType)); @@ -758,6 +770,7 @@ private JsonReaderException CreateUnexpectedCharacterException(char c) public override bool? ReadAsBoolean() { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -892,9 +905,10 @@ private void ProcessValueComma() SetStateBasedOnCurrent(); } - private object ReadNumberValue(ReadType readType) + private object? ReadNumberValue(ReadType readType) { EnsureBuffer(); + Debug.Assert(_chars != null); switch (_currentState) { @@ -1002,7 +1016,7 @@ private object ReadNumberValue(ReadType readType) } } - private object FinishReadQuotedNumber(ReadType readType) + private object? FinishReadQuotedNumber(ReadType readType) { switch (readType) { @@ -1048,6 +1062,8 @@ private object FinishReadQuotedNumber(ReadType readType) private void HandleNull() { + Debug.Assert(_chars != null); + if (EnsureChars(1, true)) { char next = _chars[_charPos + 1]; @@ -1068,6 +1084,8 @@ private void HandleNull() private void ReadFinished() { + Debug.Assert(_chars != null); + if (EnsureChars(0, false)) { EatWhitespace(); @@ -1117,6 +1135,8 @@ private void EnsureBuffer() private void ReadStringIntoBuffer(char quote) { + Debug.Assert(_chars != null); + int charPos = _charPos; int initialPosition = _charPos; int lastWritePosition = _charPos; @@ -1270,6 +1290,8 @@ private void ReadStringIntoBuffer(char quote) private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition) { + Debug.Assert(_chars != null); + if (initialPosition == lastWritePosition) { _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition); @@ -1283,7 +1305,7 @@ private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int la _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, charPos - lastWritePosition); } - _stringReference = new StringReference(_stringBuffer.InternalBuffer, 0, _stringBuffer.Position); + _stringReference = new StringReference(_stringBuffer.InternalBuffer!, 0, _stringBuffer.Position); } _charPos = charPos + 1; @@ -1291,6 +1313,8 @@ private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int la private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition) { + Debug.Assert(_chars != null); + if (writeToPosition > lastWritePosition) { _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, writeToPosition - lastWritePosition); @@ -1301,6 +1325,8 @@ private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeT private char ConvertUnicode(bool enoughChars) { + Debug.Assert(_chars != null); + if (enoughChars) { if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out int value)) @@ -1327,6 +1353,8 @@ private char ParseUnicode() private void ReadNumberIntoBuffer() { + Debug.Assert(_chars != null); + int charPos = _charPos; while (true) @@ -1411,6 +1439,8 @@ private void ClearRecentString() private bool ParsePostValue(bool ignoreComments) { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -1491,6 +1521,8 @@ private bool ParsePostValue(bool ignoreComments) private bool ParseObject() { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -1545,6 +1577,8 @@ private bool ParseObject() private bool ParseProperty() { + Debug.Assert(_chars != null); + char firstChar = _chars[_charPos]; char quoteChar; @@ -1566,7 +1600,7 @@ private bool ParseProperty() throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } - string propertyName; + string? propertyName; if (PropertyNameTable != null) { @@ -1606,6 +1640,8 @@ private bool ValidIdentifierChar(char value) private void ParseUnquotedProperty() { + Debug.Assert(_chars != null); + int initialPosition = _charPos; // parse unquoted property name until whitespace or colon @@ -1637,6 +1673,8 @@ private void ParseUnquotedProperty() private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition) { + Debug.Assert(_chars != null); + if (ValidIdentifierChar(currentChar)) { _charPos++; @@ -1654,6 +1692,8 @@ private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosit private bool ParseValue() { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -1794,6 +1834,8 @@ private void ProcessCarriageReturn(bool append) private void EatWhitespace() { + Debug.Assert(_chars != null); + while (true) { char currentChar = _chars[_charPos]; @@ -1835,6 +1877,8 @@ private void EatWhitespace() private void ParseConstructor() { + Debug.Assert(_chars != null); + if (MatchValueWithTrailingSeparator("new")) { EatWhitespace(); @@ -1919,6 +1963,7 @@ private void ParseConstructor() private void ParseNumber(ReadType readType) { ShiftBufferIfNeeded(); + Debug.Assert(_chars != null); char firstChar = _chars[_charPos]; int initialPosition = _charPos; @@ -1929,7 +1974,9 @@ private void ParseNumber(ReadType readType) } private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition) - { + { + Debug.Assert(_chars != null); + // set state to PostValue now so that if there is an error parsing the number then the reader can continue SetPostValueState(true); @@ -2190,7 +2237,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit SetToken(numberType, numberValue, false); } - private JsonReaderException ThrowReaderError(string message, Exception ex = null) + private JsonReaderException ThrowReaderError(string message, Exception? ex = null) { SetToken(JsonToken.Undefined, null, false); return JsonReaderException.Create(this, message, ex); @@ -2210,6 +2257,8 @@ private static object BigIntegerParse(string number, CultureInfo culture) private void ParseComment(bool setToken) { + Debug.Assert(_chars != null); + // should have already parsed / character before reaching this method _charPos++; @@ -2315,6 +2364,8 @@ private bool MatchValue(string value) private bool MatchValue(bool enoughChars, string value) { + Debug.Assert(_chars != null); + if (!enoughChars) { _charPos = _charsUsed; @@ -2337,6 +2388,8 @@ private bool MatchValue(bool enoughChars, string value) private bool MatchValueWithTrailingSeparator(string value) { + Debug.Assert(_chars != null); + // will match value and then move to the next character, checking that it is a separator character bool match = MatchValue(value); @@ -2355,6 +2408,8 @@ private bool MatchValueWithTrailingSeparator(string value) private bool IsSeparator(char c) { + Debug.Assert(_chars != null); + switch (c) { case '}': diff --git a/Src/Newtonsoft.Json/JsonTextWriter.Async.cs b/Src/Newtonsoft.Json/JsonTextWriter.Async.cs index 1b98a3f64..89ae0ab7e 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.Async.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.Async.cs @@ -33,6 +33,7 @@ #endif using System.Threading.Tasks; using Newtonsoft.Json.Utilities; +using System.Diagnostics; namespace Newtonsoft.Json { @@ -164,6 +165,7 @@ internal Task DoWriteIndentAsync(CancellationToken cancellationToken) int currentIndentCount = Top * _indentation; int newLineLen = SetIndentChars(); + Debug.Assert(_indentChars != null); if (currentIndentCount <= IndentCharBufferSize) { @@ -175,6 +177,8 @@ internal Task DoWriteIndentAsync(CancellationToken cancellationToken) private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken) { + Debug.Assert(_indentChars != null); + await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize), cancellationToken).ConfigureAwait(false); while ((currentIndentCount -= IndentCharBufferSize) > 0) @@ -225,12 +229,12 @@ internal Task DoWriteIndentSpaceAsync(CancellationToken cancellationToken) /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteRawAsync(string json, CancellationToken cancellationToken = default) + public override Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) { return _safeAsync ? DoWriteRawAsync(json, cancellationToken) : base.WriteRawAsync(json, cancellationToken); } - internal Task DoWriteRawAsync(string json, CancellationToken cancellationToken) + internal Task DoWriteRawAsync(string? json, CancellationToken cancellationToken) { return _writer.WriteAsync(json, cancellationToken); } @@ -260,7 +264,7 @@ private Task WriteDigitsAsync(ulong uvalue, bool negative, CancellationToken can } int length = WriteNumberToBuffer(uvalue, negative); - return _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken); + return _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken); } private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) @@ -298,7 +302,7 @@ internal Task WriteIntegerValueAsync(ulong uvalue, CancellationToken cancellatio private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken) { - return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, this, _writeBuffer, cancellationToken); + return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, this, _writeBuffer!, cancellationToken); } /// @@ -585,7 +589,7 @@ internal Task DoWriteValueAsync(byte? value, CancellationToken cancellationToken /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(byte[] value, CancellationToken cancellationToken = default) + public override Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) { return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNonNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); } @@ -657,7 +661,7 @@ internal async Task DoWriteValueAsync(DateTime value, CancellationToken cancella { int length = WriteValueToBuffer(value); - await _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); } else { @@ -706,7 +710,7 @@ internal async Task DoWriteValueAsync(DateTimeOffset value, CancellationToken ca { int length = WriteValueToBuffer(value); - await _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); } else { @@ -953,7 +957,7 @@ internal Task WriteValueAsync(BigInteger value, CancellationToken cancellationTo /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(object value, CancellationToken cancellationToken = default) + public override Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) { if (_safeAsync) { @@ -1046,12 +1050,12 @@ internal Task DoWriteValueAsync(short? value, CancellationToken cancellationToke /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(string value, CancellationToken cancellationToken = default) + public override Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) { return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); } - internal Task DoWriteValueAsync(string value, CancellationToken cancellationToken) + internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); if (task.IsCompletedSucessfully()) @@ -1062,7 +1066,7 @@ internal Task DoWriteValueAsync(string value, CancellationToken cancellationToke return DoWriteValueAsync(task, value, cancellationToken); } - private async Task DoWriteValueAsync(Task task, string value, CancellationToken cancellationToken) + private async Task DoWriteValueAsync(Task task, string? value, CancellationToken cancellationToken) { await task.ConfigureAwait(false); await (value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken)).ConfigureAwait(false); @@ -1181,7 +1185,7 @@ internal Task DoWriteValueAsync(ulong? value, CancellationToken cancellationToke /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteValueAsync(Uri value, CancellationToken cancellationToken = default) + public override Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) { return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNotNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); } @@ -1244,16 +1248,16 @@ internal Task DoWriteValueAsync(ushort? value, CancellationToken cancellationTok /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteCommentAsync(string text, CancellationToken cancellationToken = default) + public override Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) { return _safeAsync ? DoWriteCommentAsync(text, cancellationToken) : base.WriteCommentAsync(text, cancellationToken); } - internal async Task DoWriteCommentAsync(string text, CancellationToken cancellationToken) + internal async Task DoWriteCommentAsync(string? text, CancellationToken cancellationToken) { await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(false); await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(false); - await _writer.WriteAsync(text, cancellationToken).ConfigureAwait(false); + await _writer.WriteAsync(text ?? string.Empty, cancellationToken).ConfigureAwait(false); await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(false); } @@ -1301,12 +1305,12 @@ public override Task WriteEndObjectAsync(CancellationToken cancellationToken = d /// A that represents the asynchronous operation. /// Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// execute synchronously, returning an already-completed task. - public override Task WriteRawValueAsync(string json, CancellationToken cancellationToken = default) + public override Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) { return _safeAsync ? DoWriteRawValueAsync(json, cancellationToken) : base.WriteRawValueAsync(json, cancellationToken); } - internal Task DoWriteRawValueAsync(string json, CancellationToken cancellationToken) + internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationToken) { UpdateScopeWithFinishedValue(); Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); @@ -1318,7 +1322,7 @@ internal Task DoWriteRawValueAsync(string json, CancellationToken cancellationTo return DoWriteRawValueAsync(task, json, cancellationToken); } - private async Task DoWriteRawValueAsync(Task task, string json, CancellationToken cancellationToken) + private async Task DoWriteRawValueAsync(Task task, string? json, CancellationToken cancellationToken) { await task.ConfigureAwait(false); await WriteRawAsync(json, cancellationToken).ConfigureAwait(false); @@ -1331,7 +1335,7 @@ internal char[] EnsureWriteBuffer(int length, int copyTo) length = 35; } - char[] buffer = _writeBuffer; + char[]? buffer = _writeBuffer; if (buffer == null) { return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length); diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index 6b7abd91d..2bb21ee80 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -33,6 +33,7 @@ using System.IO; using System.Xml; using Newtonsoft.Json.Utilities; +using System.Diagnostics; namespace Newtonsoft.Json { @@ -43,15 +44,15 @@ public partial class JsonTextWriter : JsonWriter { private const int IndentCharBufferSize = 12; private readonly TextWriter _writer; - private Base64Encoder _base64Encoder; + private Base64Encoder? _base64Encoder; private char _indentChar; private int _indentation; private char _quoteChar; private bool _quoteName; - private bool[] _charEscapeFlags; - private char[] _writeBuffer; - private IArrayPool _arrayPool; - private char[] _indentChars; + private bool[]? _charEscapeFlags; + private char[]? _writeBuffer; + private IArrayPool? _arrayPool; + private char[]? _indentChars; private Base64Encoder Base64Encoder { @@ -69,7 +70,7 @@ private Base64Encoder Base64Encoder /// /// Gets or sets the writer's character array pool. /// - public IArrayPool ArrayPool + public IArrayPool? ArrayPool { get => _arrayPool; set @@ -342,7 +343,7 @@ private int SetIndentChars() { for (int i = 0; i != newLineLen; ++i) { - if (writerNewLine[i] != _indentChars[i]) + if (writerNewLine[i] != _indentChars![i]) { match = false; break; @@ -387,7 +388,7 @@ private void WriteValueInternal(string value, JsonToken token) /// An error will raised if the value cannot be written as a single JSON token. /// /// The value to write. - public override void WriteValue(object value) + public override void WriteValue(object? value) { #if HAVE_BIG_INTEGER if (value is BigInteger i) @@ -424,7 +425,7 @@ public override void WriteUndefined() /// Writes raw JSON. /// /// The raw JSON to write. - public override void WriteRaw(string json) + public override void WriteRaw(string? json) { InternalWriteRaw(); @@ -435,7 +436,7 @@ public override void WriteRaw(string json) /// Writes a value. /// /// The value to write. - public override void WriteValue(string value) + public override void WriteValue(string? value) { InternalWriteValue(JsonToken.String); @@ -452,7 +453,7 @@ public override void WriteValue(string value) private void WriteEscapedString(string value, bool quote) { EnsureWriteBuffer(); - JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, _arrayPool, ref _writeBuffer); + JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, _arrayPool, ref _writeBuffer); } /// @@ -649,6 +650,7 @@ public override void WriteValue(DateTime value) private int WriteValueToBuffer(DateTime value) { EnsureWriteBuffer(); + Debug.Assert(_writeBuffer != null); int pos = 0; _writeBuffer[pos++] = _quoteChar; @@ -661,7 +663,7 @@ private int WriteValueToBuffer(DateTime value) /// Writes a [] value. /// /// The [] value to write. - public override void WriteValue(byte[] value) + public override void WriteValue(byte[]? value) { if (value == null) { @@ -703,6 +705,7 @@ public override void WriteValue(DateTimeOffset value) private int WriteValueToBuffer(DateTimeOffset value) { EnsureWriteBuffer(); + Debug.Assert(_writeBuffer != null); int pos = 0; _writeBuffer[pos++] = _quoteChar; @@ -720,7 +723,7 @@ public override void WriteValue(Guid value) { InternalWriteValue(JsonToken.String); - string text = null; + string text; #if HAVE_CHAR_TO_STRING_WITH_CULTURE text = value.ToString("D", CultureInfo.InvariantCulture); @@ -757,7 +760,7 @@ public override void WriteValue(TimeSpan value) /// Writes a value. /// /// The value to write. - public override void WriteValue(Uri value) + public override void WriteValue(Uri? value) { if (value == null) { @@ -775,7 +778,7 @@ public override void WriteValue(Uri value) /// Writes a comment /*...*/ containing the specified text. /// /// Text to place inside the comment. - public override void WriteComment(string text) + public override void WriteComment(string? text) { InternalWriteComment(); @@ -839,6 +842,7 @@ private int WriteNumberToBuffer(ulong value, bool negative) } EnsureWriteBuffer(); + Debug.Assert(_writeBuffer != null); int totalLength = MathUtils.IntLength(value); @@ -890,6 +894,7 @@ private void WriteIntegerValue(uint value, bool negative) private int WriteNumberToBuffer(uint value, bool negative) { EnsureWriteBuffer(); + Debug.Assert(_writeBuffer != null); int totalLength = MathUtils.IntLength(value); diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs index 34cc3ae6f..7b6de5902 100644 --- a/Src/Newtonsoft.Json/JsonValidatingReader.cs +++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs @@ -41,6 +41,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json { /// diff --git a/Src/Newtonsoft.Json/JsonWriter.Async.cs b/Src/Newtonsoft.Json/JsonWriter.Async.cs index 4a9c0f7d6..47c6325e4 100644 --- a/Src/Newtonsoft.Json/JsonWriter.Async.cs +++ b/Src/Newtonsoft.Json/JsonWriter.Async.cs @@ -225,7 +225,7 @@ protected virtual Task WriteIndentSpaceAsync(CancellationToken cancellationToken /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteRawAsync(string json, CancellationToken cancellationToken = default) + public virtual Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -546,7 +546,7 @@ internal async Task InternalWriteStartAsync(JsonToken token, JsonContainerType c /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteCommentAsync(string text, CancellationToken cancellationToken = default) + public virtual Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -570,7 +570,7 @@ internal Task InternalWriteCommentAsync(CancellationToken cancellationToken) /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteRawValueAsync(string json, CancellationToken cancellationToken = default) + public virtual Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -673,7 +673,7 @@ public Task WriteTokenAsync(JsonToken token, CancellationToken cancellationToken /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public Task WriteTokenAsync(JsonToken token, object value, CancellationToken cancellationToken = default) + public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -755,7 +755,7 @@ public Task WriteTokenAsync(JsonToken token, object value, CancellationToken can return WriteValueAsync(guid, cancellationToken); } - return WriteValueAsync((byte[])value, cancellationToken); + return WriteValueAsync((byte[]?)value, cancellationToken); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token), token, "Unexpected token type."); } @@ -768,7 +768,7 @@ internal virtual async Task WriteTokenAsync(JsonReader reader, bool writeChildre do { // write a JValue date when the constructor is for a date - if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal)) + if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(false); } @@ -801,7 +801,7 @@ internal async Task WriteTokenSyncReadingAsync(JsonReader reader, CancellationTo do { // write a JValue date when the constructor is for a date - if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal)) + if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } @@ -831,7 +831,7 @@ private async Task WriteConstructorDateAsync(JsonReader reader, CancellationToke throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null); } - DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value); + DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value!); if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { @@ -929,7 +929,7 @@ public virtual Task WriteValueAsync(byte? value, CancellationToken cancellationT /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(byte[] value, CancellationToken cancellationToken = default) + public virtual Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -1290,7 +1290,7 @@ public virtual Task WriteValueAsync(long? value, CancellationToken cancellationT /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(object value, CancellationToken cancellationToken = default) + public virtual Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -1387,7 +1387,7 @@ public virtual Task WriteValueAsync(short? value, CancellationToken cancellation /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(string value, CancellationToken cancellationToken = default) + public virtual Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { @@ -1524,7 +1524,7 @@ public virtual Task WriteValueAsync(ulong? value, CancellationToken cancellation /// A that represents the asynchronous operation. /// The default behaviour is to execute synchronously, returning an already-completed task. Derived /// classes can override this behaviour for true asynchronicity. - public virtual Task WriteValueAsync(Uri value, CancellationToken cancellationToken = default) + public virtual Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index c253585b5..893ecb3f2 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -116,7 +116,7 @@ static JsonWriter() StateArray = BuildStateArray(); } - private List _stack; + private List? _stack; private JsonPosition _currentPosition; private State _currentState; private Formatting _formatting; @@ -218,7 +218,7 @@ public string Path JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null; - return JsonPosition.BuildPath(_stack, current); + return JsonPosition.BuildPath(_stack!, current); } } @@ -226,8 +226,8 @@ public string Path private DateTimeZoneHandling _dateTimeZoneHandling; private StringEscapeHandling _stringEscapeHandling; private FloatFormatHandling _floatFormatHandling; - private string _dateFormatString; - private CultureInfo _culture; + private string? _dateFormatString; + private CultureInfo? _culture; /// /// Gets or sets a value indicating how JSON text output should be formatted. @@ -325,7 +325,7 @@ public FloatFormatHandling FloatFormatHandling /// /// Gets or sets how and values are formatted when writing JSON text. /// - public string DateFormatString + public string? DateFormatString { get => _dateFormatString; set => _dateFormatString = value; @@ -522,7 +522,7 @@ public void WriteToken(JsonReader reader, bool writeChildren) /// A value is only required for tokens that have an associated value, e.g. the property name for . /// null can be passed to the method for tokens that don't have a value, e.g. . /// - public void WriteToken(JsonToken token, object value) + public void WriteToken(JsonToken token, object? value) { switch (token) { @@ -625,7 +625,7 @@ public void WriteToken(JsonToken token, object value) } else { - WriteValue((byte[])value); + WriteValue((byte[])value!); } break; default: @@ -649,7 +649,7 @@ internal virtual void WriteToken(JsonReader reader, bool writeChildren, bool wri do { // write a JValue date when the constructor is for a date - if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal)) + if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } @@ -696,7 +696,7 @@ private int CalculateWriteTokenFinalDepth(JsonReader reader) private void WriteConstructorDate(JsonReader reader) { - if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage)) + if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string? errorMessage)) { throw JsonWriterException.Create(this, errorMessage, null); } @@ -787,7 +787,7 @@ private int CalculateLevelsToComplete(JsonContainerType type) { int currentLevel = top - i; - if (_stack[currentLevel].Type == type) + if (_stack![currentLevel].Type == type) { levelsToComplete = i + 2; break; @@ -909,7 +909,7 @@ public virtual void WriteUndefined() /// Writes raw JSON without changing the writer's state. /// /// The raw JSON to write. - public virtual void WriteRaw(string json) + public virtual void WriteRaw(string? json) { InternalWriteRaw(); } @@ -918,7 +918,7 @@ public virtual void WriteRaw(string json) /// Writes raw JSON where a value is expected and updates the writer's state. /// /// The raw JSON to write. - public virtual void WriteRawValue(string json) + public virtual void WriteRawValue(string? json) { // hack. want writer to change state as if a value had been written UpdateScopeWithFinishedValue(); @@ -930,7 +930,7 @@ public virtual void WriteRawValue(string json) /// Writes a value. /// /// The value to write. - public virtual void WriteValue(string value) + public virtual void WriteValue(string? value) { InternalWriteValue(JsonToken.String); } @@ -1376,7 +1376,7 @@ public virtual void WriteValue(TimeSpan? value) /// Writes a [] value. /// /// The [] value to write. - public virtual void WriteValue(byte[] value) + public virtual void WriteValue(byte[]? value) { if (value == null) { @@ -1392,7 +1392,7 @@ public virtual void WriteValue(byte[] value) /// Writes a value. /// /// The value to write. - public virtual void WriteValue(Uri value) + public virtual void WriteValue(Uri? value) { if (value == null) { @@ -1409,7 +1409,7 @@ public virtual void WriteValue(Uri value) /// An error will raised if the value cannot be written as a single JSON token. /// /// The value to write. - public virtual void WriteValue(object value) + public virtual void WriteValue(object? value) { if (value == null) { @@ -1435,7 +1435,7 @@ public virtual void WriteValue(object value) /// Writes a comment /*...*/ containing the specified text. /// /// Text to place inside the comment. - public virtual void WriteComment(string text) + public virtual void WriteComment(string? text) { InternalWriteComment(); } diff --git a/Src/Newtonsoft.Json/JsonWriterException.cs b/Src/Newtonsoft.Json/JsonWriterException.cs index 4312b6bac..cb5b9ac7c 100644 --- a/Src/Newtonsoft.Json/JsonWriterException.cs +++ b/Src/Newtonsoft.Json/JsonWriterException.cs @@ -42,7 +42,7 @@ public class JsonWriterException : JsonException /// Gets the path to the JSON where the error occurred. /// /// The path to the JSON where the error occurred. - public string Path { get; } + public string? Path { get; } /// /// Initializes a new instance of the class. @@ -93,18 +93,18 @@ public JsonWriterException(SerializationInfo info, StreamingContext context) /// The error message that explains the reason for the exception. /// The path to the JSON where the error occurred. /// The exception that is the cause of the current exception, or null if no inner exception is specified. - public JsonWriterException(string message, string path, Exception innerException) + public JsonWriterException(string message, string path, Exception? innerException) : base(message, innerException) { Path = path; } - internal static JsonWriterException Create(JsonWriter writer, string message, Exception ex) + internal static JsonWriterException Create(JsonWriter writer, string message, Exception? ex) { return Create(writer.ContainerPath, message, ex); } - internal static JsonWriterException Create(string path, string message, Exception ex) + internal static JsonWriterException Create(string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(null, path, message); diff --git a/Src/Newtonsoft.Json/Linq/Extensions.cs b/Src/Newtonsoft.Json/Linq/Extensions.cs index 43b70d4bc..da19f8a27 100644 --- a/Src/Newtonsoft.Json/Linq/Extensions.cs +++ b/Src/Newtonsoft.Json/Linq/Extensions.cs @@ -27,6 +27,8 @@ using System.Collections.Generic; using Newtonsoft.Json.Utilities; using System.Globalization; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -111,7 +113,7 @@ public static IJEnumerable Properties(this IEnumerable sourc /// An of that contains the source collection. /// The token key. /// An of that contains the values of every token in the source collection with the given key. - public static IJEnumerable Values(this IEnumerable source, object key) + public static IJEnumerable Values(this IEnumerable source, object? key) { return Values(source, key).AsJEnumerable(); } @@ -179,7 +181,7 @@ public static U Value(this IEnumerable value) where T : JToken return token.Convert(); } - internal static IEnumerable Values(this IEnumerable source, object key) where T : JToken + internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken { ValidationUtils.ArgumentNotNull(source, nameof(source)); @@ -204,7 +206,7 @@ internal static IEnumerable Values(this IEnumerable source, object k { foreach (T token in source) { - JToken value = token[key]; + JToken? value = token[key]; if (value != null) { yield return value.Convert(); @@ -251,11 +253,14 @@ internal static IEnumerable Convert(this IEnumerable source) where T } } - internal static U Convert(this T token) where T : JToken + [return: MaybeNull] + internal static U Convert(this T token) where T : JToken? { if (token == null) { +#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. return default; +#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. } if (token is U castValue @@ -282,7 +287,9 @@ internal static U Convert(this T token) where T : JToken { if (value.Value == null) { +#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. return default; +#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. } targetType = Nullable.GetUnderlyingType(targetType); @@ -315,7 +322,7 @@ public static IJEnumerable AsJEnumerable(this IEnumerable source) where { if (source == null) { - return null; + return null!; } else if (source is IJEnumerable customEnumerable) { diff --git a/Src/Newtonsoft.Json/Linq/JArray.Async.cs b/Src/Newtonsoft.Json/Linq/JArray.Async.cs index ef6bdf523..25ffe4efe 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.Async.cs @@ -73,7 +73,7 @@ public override async Task WriteToAsync(JsonWriter writer, CancellationToken can /// If this is null, default load settings will be used. /// The token to monitor for cancellation requests. The default value is . /// A representing the asynchronous load. The property contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { if (reader.TokenType == JsonToken.None) { diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs index 270027e84..241a56045 100644 --- a/Src/Newtonsoft.Json/Linq/JArray.cs +++ b/Src/Newtonsoft.Json/Linq/JArray.cs @@ -115,7 +115,7 @@ internal override JToken CloneToken() /// The used to load the JSON. /// If this is null, default load settings will be used. /// A that contains the JSON that was read from the specified . - public new static JArray Load(JsonReader reader, JsonLoadSettings settings) + public new static JArray Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None) { @@ -163,7 +163,7 @@ internal override JToken CloneToken() /// /// /// - public new static JArray Parse(string json, JsonLoadSettings settings) + public new static JArray Parse(string json, JsonLoadSettings? settings) { using (JsonReader reader = new JsonTextReader(new StringReader(json))) { @@ -227,7 +227,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter /// Gets the with the specified key. /// /// The with the specified key. - public override JToken this[object key] + public override JToken? this[object key] { get { @@ -263,14 +263,19 @@ public JToken this[int index] set => SetItem(index, value); } - internal override int IndexOfItem(JToken item) + internal override int IndexOfItem(JToken? item) { + if (item == null) + { + return -1; + } + return _values.IndexOfReference(item); } - internal override void MergeItem(object content, JsonMergeSettings settings) + internal override void MergeItem(object content, JsonMergeSettings? settings) { - IEnumerable a = (IsMultiContent(content) || content is JArray) + IEnumerable? a = (IsMultiContent(content) || content is JArray) ? (IEnumerable)content : null; if (a == null) diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.Async.cs b/Src/Newtonsoft.Json/Linq/JConstructor.Async.cs index d24b81f82..bdbeff69a 100644 --- a/Src/Newtonsoft.Json/Linq/JConstructor.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JConstructor.Async.cs @@ -43,7 +43,7 @@ public partial class JConstructor /// A that represents the asynchronous write operation. public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { - await writer.WriteStartConstructorAsync(_name, cancellationToken).ConfigureAwait(false); + await writer.WriteStartConstructorAsync(_name ?? string.Empty, cancellationToken).ConfigureAwait(false); for (int i = 0; i < _values.Count; i++) { @@ -76,7 +76,7 @@ public override async Task WriteToAsync(JsonWriter writer, CancellationToken can /// /// A that represents the asynchronous load. The /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { if (reader.TokenType == JsonToken.None) { @@ -93,7 +93,7 @@ public override async Task WriteToAsync(JsonWriter writer, CancellationToken can throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - JConstructor c = new JConstructor((string)reader.Value); + JConstructor c = new JConstructor((string)reader.Value!); c.SetLineInfo(reader as IJsonLineInfo, settings); await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs index 759008fd6..4903c0a24 100644 --- a/Src/Newtonsoft.Json/Linq/JConstructor.cs +++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs @@ -36,7 +36,7 @@ namespace Newtonsoft.Json.Linq /// public partial class JConstructor : JContainer { - private string _name; + private string? _name; private readonly List _values = new List(); /// @@ -45,12 +45,17 @@ public partial class JConstructor : JContainer /// The container's children tokens. protected override IList ChildrenTokens => _values; - internal override int IndexOfItem(JToken item) + internal override int IndexOfItem(JToken? item) { + if (item == null) + { + return -1; + } + return _values.IndexOfReference(item); } - internal override void MergeItem(object content, JsonMergeSettings settings) + internal override void MergeItem(object content, JsonMergeSettings? settings) { if (!(content is JConstructor c)) { @@ -68,7 +73,7 @@ internal override void MergeItem(object content, JsonMergeSettings settings) /// Gets or sets the name of this constructor. /// /// The constructor name. - public string Name + public string? Name { get => _name; set => _name = value; @@ -154,7 +159,7 @@ internal override JToken CloneToken() /// A collection of which will be used when writing the token. public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { - writer.WriteStartConstructor(_name); + writer.WriteStartConstructor(_name!); int count = _values.Count; for (int i = 0; i < count; i++) @@ -169,7 +174,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter /// Gets the with the specified key. /// /// The with the specified key. - public override JToken this[object key] + public override JToken? this[object key] { get { @@ -197,7 +202,7 @@ public override JToken this[object key] internal override int GetDeepHashCode() { - return _name.GetHashCode() ^ ContentsHashCode(); + return (_name?.GetHashCode() ?? 0) ^ ContentsHashCode(); } /// @@ -217,7 +222,7 @@ internal override int GetDeepHashCode() /// The used to load the JSON. /// If this is null, default load settings will be used. /// A that contains the JSON that was read from the specified . - public new static JConstructor Load(JsonReader reader, JsonLoadSettings settings) + public new static JConstructor Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None) { @@ -234,7 +239,7 @@ internal override int GetDeepHashCode() throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - JConstructor c = new JConstructor((string)reader.Value); + JConstructor c = new JConstructor((string)reader.Value!); c.SetLineInfo(reader as IJsonLineInfo, settings); c.ReadTokenFrom(reader, settings); diff --git a/Src/Newtonsoft.Json/Linq/JContainer.Async.cs b/Src/Newtonsoft.Json/Linq/JContainer.Async.cs index 7aee837cd..455ed8ff1 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.Async.cs @@ -26,6 +26,7 @@ #if HAVE_ASYNC using System; +using System.Diagnostics; using System.Globalization; using System.Threading; using System.Threading.Tasks; @@ -35,7 +36,7 @@ namespace Newtonsoft.Json.Linq { public abstract partial class JContainer { - internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings options, CancellationToken cancellationToken = default) + internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings? options, CancellationToken cancellationToken = default) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); int startDepth = reader.Depth; @@ -53,11 +54,11 @@ internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings optio } } - private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { - IJsonLineInfo lineInfo = reader as IJsonLineInfo; + IJsonLineInfo? lineInfo = reader as IJsonLineInfo; - JContainer parent = this; + JContainer? parent = this; do { @@ -71,6 +72,8 @@ private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings sett parent = parent.Parent; } + Debug.Assert(parent != null); + switch (reader.TokenType) { case JsonToken.None: @@ -106,7 +109,7 @@ private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings sett parent = parent.Parent; break; case JsonToken.StartConstructor: - JConstructor constructor = new JConstructor(reader.Value.ToString()); + JConstructor constructor = new JConstructor(reader.Value!.ToString()); constructor.SetLineInfo(lineInfo, settings); parent.Add(constructor); parent = constructor; @@ -132,7 +135,7 @@ private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings sett case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { - v = JValue.CreateComment(reader.Value.ToString()); + v = JValue.CreateComment(reader.Value!.ToString()); v.SetLineInfo(lineInfo, settings); parent.Add(v); } @@ -148,7 +151,7 @@ private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings sett parent.Add(v); break; case JsonToken.PropertyName: - JProperty property = ReadProperty(reader, settings, lineInfo, parent); + JProperty? property = ReadProperty(reader, settings, lineInfo, parent); if (property != null) { parent = property; diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index 2ad8fa408..f1d8ed093 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -33,11 +33,13 @@ using System.Collections; using System.Globalization; using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; - #endif namespace Newtonsoft.Json.Linq @@ -55,8 +57,8 @@ namespace Newtonsoft.Json.Linq #endif { #if HAVE_COMPONENT_MODEL - internal ListChangedEventHandler _listChanged; - internal AddingNewEventHandler _addingNew; + internal ListChangedEventHandler? _listChanged; + internal AddingNewEventHandler? _addingNew; /// /// Occurs when the list changes or an item in the list changes. @@ -77,7 +79,7 @@ public event AddingNewEventHandler AddingNew } #endif #if HAVE_INOTIFY_COLLECTION_CHANGED - internal NotifyCollectionChangedEventHandler _collectionChanged; + internal NotifyCollectionChangedEventHandler? _collectionChanged; /// /// Occurs when the items list of the collection has changed, or the collection is reset. @@ -95,7 +97,7 @@ public event NotifyCollectionChangedEventHandler CollectionChanged /// The container's children tokens. protected abstract IList ChildrenTokens { get; } - private object _syncRoot; + private object? _syncRoot; #if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED) private bool _busy; #endif @@ -148,7 +150,7 @@ protected virtual void OnAddingNew(AddingNewEventArgs e) /// The instance containing the event data. protected virtual void OnListChanged(ListChangedEventArgs e) { - ListChangedEventHandler handler = _listChanged; + ListChangedEventHandler? handler = _listChanged; if (handler != null) { @@ -171,7 +173,7 @@ protected virtual void OnListChanged(ListChangedEventArgs e) /// The instance containing the event data. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { - NotifyCollectionChangedEventHandler handler = _collectionChanged; + NotifyCollectionChangedEventHandler? handler = _collectionChanged; if (handler != null) { @@ -228,7 +230,7 @@ internal bool ContentsEqual(JContainer container) /// /// A containing the first child token of the . /// - public override JToken First + public override JToken? First { get { @@ -243,7 +245,7 @@ public override JToken First /// /// A containing the last child token of the . /// - public override JToken Last + public override JToken? Last { get { @@ -314,12 +316,12 @@ internal IEnumerable GetDescendants(bool self) } } - internal bool IsMultiContent(object content) + internal bool IsMultiContent([NotNull]object? content) { return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[])); } - internal JToken EnsureParentToken(JToken item, bool skipParentCheck) + internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) { if (item == null) { @@ -343,9 +345,9 @@ internal JToken EnsureParentToken(JToken item, bool skipParentCheck) return item; } - internal abstract int IndexOfItem(JToken item); + internal abstract int IndexOfItem(JToken? item); - internal virtual void InsertItem(int index, JToken item, bool skipParentCheck) + internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck) { IList children = ChildrenTokens; @@ -358,9 +360,9 @@ internal virtual void InsertItem(int index, JToken item, bool skipParentCheck) item = EnsureParentToken(item, skipParentCheck); - JToken previous = (index == 0) ? null : children[index - 1]; + JToken? previous = (index == 0) ? null : children[index - 1]; // haven't inserted new token yet so next token is still at the inserting index - JToken next = (index == children.Count) ? null : children[index]; + JToken? next = (index == children.Count) ? null : children[index]; ValidateToken(item, null); @@ -410,8 +412,8 @@ internal virtual void RemoveItemAt(int index) CheckReentrancy(); JToken item = children[index]; - JToken previous = (index == 0) ? null : children[index - 1]; - JToken next = (index == children.Count - 1) ? null : children[index + 1]; + JToken? previous = (index == 0) ? null : children[index - 1]; + JToken? next = (index == children.Count - 1) ? null : children[index + 1]; if (previous != null) { @@ -442,13 +444,16 @@ internal virtual void RemoveItemAt(int index) #endif } - internal virtual bool RemoveItem(JToken item) + internal virtual bool RemoveItem(JToken? item) { - int index = IndexOfItem(item); - if (index >= 0) + if (item != null) { - RemoveItemAt(index); - return true; + int index = IndexOfItem(item); + if (index >= 0) + { + RemoveItemAt(index); + return true; + } } return false; @@ -459,7 +464,7 @@ internal virtual JToken GetItem(int index) return ChildrenTokens[index]; } - internal virtual void SetItem(int index, JToken item) + internal virtual void SetItem(int index, JToken? item) { IList children = ChildrenTokens; @@ -485,8 +490,8 @@ internal virtual void SetItem(int index, JToken item) ValidateToken(item, existing); - JToken previous = (index == 0) ? null : children[index - 1]; - JToken next = (index == children.Count - 1) ? null : children[index + 1]; + JToken? previous = (index == 0) ? null : children[index - 1]; + JToken? next = (index == children.Count - 1) ? null : children[index + 1]; item.Parent = this; @@ -562,7 +567,7 @@ internal virtual void ReplaceItem(JToken existing, JToken replacement) SetItem(index, replacement); } - internal virtual bool ContainsItem(JToken item) + internal virtual bool ContainsItem(JToken? item) { return (IndexOfItem(item) != -1); } @@ -594,14 +599,14 @@ internal virtual void CopyItemsTo(Array array, int arrayIndex) } } - internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue) + internal static bool IsTokenUnchanged(JToken currentValue, JToken? newValue) { if (currentValue is JValue v1) { - // null will get turned into a JValue of type null - if (v1.Type == JTokenType.Null && newValue == null) + if (newValue == null) { - return true; + // null will get turned into a JValue of type null + return v1.Type == JTokenType.Null; } return v1.Equals(newValue); @@ -610,7 +615,7 @@ internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue) return false; } - internal virtual void ValidateToken(JToken o, JToken existing) + internal virtual void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, nameof(o)); @@ -624,7 +629,7 @@ internal virtual void ValidateToken(JToken o, JToken existing) /// Adds the specified content as children of this . /// /// The content to be added. - public virtual void Add(object content) + public virtual void Add(object? content) { AddInternal(ChildrenTokens.Count, content, false); } @@ -638,12 +643,12 @@ internal void AddAndSkipParentCheck(JToken token) /// Adds the specified content as the first children of this . /// /// The content to be added. - public void AddFirst(object content) + public void AddFirst(object? content) { AddInternal(0, content, false); } - internal void AddInternal(int index, object content, bool skipParentCheck) + internal void AddInternal(int index, object? content, bool skipParentCheck) { if (IsMultiContent(content)) { @@ -664,7 +669,7 @@ internal void AddInternal(int index, object content, bool skipParentCheck) } } - internal static JToken CreateFromContent(object content) + internal static JToken CreateFromContent(object? content) { if (content is JToken token) { @@ -701,7 +706,7 @@ public void RemoveAll() ClearItems(); } - internal abstract void MergeItem(object content, JsonMergeSettings settings); + internal abstract void MergeItem(object content, JsonMergeSettings? settings); /// /// Merge the specified content into this . @@ -709,7 +714,7 @@ public void RemoveAll() /// The content to be merged. public void Merge(object content) { - MergeItem(content, new JsonMergeSettings()); + MergeItem(content, null); } /// @@ -717,12 +722,12 @@ public void Merge(object content) /// /// The content to be merged. /// The used to merge the content. - public void Merge(object content, JsonMergeSettings settings) + public void Merge(object content, JsonMergeSettings? settings) { MergeItem(content, settings); } - internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings options) + internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) { int startDepth = reader.Depth; @@ -741,12 +746,12 @@ internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings options) } } - internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) + internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(r, nameof(r)); - IJsonLineInfo lineInfo = r as IJsonLineInfo; + IJsonLineInfo? lineInfo = r as IJsonLineInfo; - JContainer parent = this; + JContainer? parent = this; do { @@ -760,6 +765,8 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) parent = parent.Parent; } + Debug.Assert(parent != null); + switch (r.TokenType) { case JsonToken.None: @@ -795,7 +802,7 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) parent = parent.Parent; break; case JsonToken.StartConstructor: - JConstructor constructor = new JConstructor(r.Value.ToString()); + JConstructor constructor = new JConstructor(r.Value!.ToString()); constructor.SetLineInfo(lineInfo, settings); parent.Add(constructor); parent = constructor; @@ -821,7 +828,7 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { - v = JValue.CreateComment(r.Value.ToString()); + v = JValue.CreateComment(r.Value!.ToString()); v.SetLineInfo(lineInfo, settings); parent.Add(v); } @@ -837,7 +844,7 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) parent.Add(v); break; case JsonToken.PropertyName: - JProperty property = ReadProperty(r, settings, lineInfo, parent); + JProperty? property = ReadProperty(r, settings, lineInfo, parent); if (property != null) { parent = property; @@ -853,13 +860,13 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings) } while (r.Read()); } - private static JProperty ReadProperty(JsonReader r, JsonLoadSettings settings, IJsonLineInfo lineInfo, JContainer parent) + private static JProperty? ReadProperty(JsonReader r, JsonLoadSettings? settings, IJsonLineInfo? lineInfo, JContainer parent) { DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; JObject parentObject = (JObject)parent; - string propertyName = r.Value.ToString(); - JProperty existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal); + string propertyName = r.Value!.ToString(); + JProperty? existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal); if (existingPropertyWithName != null) { if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore) @@ -903,9 +910,9 @@ string ITypedList.GetListName(PropertyDescriptor[] listAccessors) return string.Empty; } - PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) + PropertyDescriptorCollection? ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { - ICustomTypeDescriptor d = First as ICustomTypeDescriptor; + ICustomTypeDescriptor? d = First as ICustomTypeDescriptor; return d?.GetProperties(); } #endif @@ -962,7 +969,7 @@ bool ICollection.Remove(JToken item) } #endregion - private JToken EnsureValue(object value) + private JToken? EnsureValue(object value) { if (value == null) { @@ -1108,7 +1115,7 @@ void IBindingList.RemoveSort() ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending; - PropertyDescriptor IBindingList.SortProperty => null; + PropertyDescriptor? IBindingList.SortProperty => null; bool IBindingList.SupportsChangeNotification => true; @@ -1118,9 +1125,9 @@ void IBindingList.RemoveSort() #endif #endregion - internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings settings) + internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings? settings) { - switch (settings.MergeArrayHandling) + switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: foreach (JToken item in content) @@ -1169,7 +1176,7 @@ internal static void MergeEnumerableContent(JContainer target, IEnumerable conte { if (i < target.Count) { - JToken sourceItem = target[i]; + JToken? sourceItem = target[i]; if (sourceItem is JContainer existingContainer) { diff --git a/Src/Newtonsoft.Json/Linq/JObject.Async.cs b/Src/Newtonsoft.Json/Linq/JObject.Async.cs index 21eb02b76..d973e8bc1 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.Async.cs @@ -97,7 +97,7 @@ async Task AwaitProperties(Task task, int i, JsonWriter Writer, CancellationToke /// /// A that represents the asynchronous load. The /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 6ae7436df..7bfb525b5 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -37,6 +37,8 @@ using System.IO; using Newtonsoft.Json.Utilities; using System.Globalization; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -51,7 +53,7 @@ namespace Newtonsoft.Json.Linq /// /// /// - public partial class JObject : JContainer, IDictionary, INotifyPropertyChanged + public partial class JObject : JContainer, IDictionary, INotifyPropertyChanged #if HAVE_COMPONENT_MODEL , ICustomTypeDescriptor #endif @@ -123,12 +125,17 @@ internal override bool DeepEquals(JToken node) return _properties.Compare(t._properties); } - internal override int IndexOfItem(JToken item) + internal override int IndexOfItem(JToken? item) { + if (item == null) + { + return -1; + } + return _properties.IndexOfReference(item); } - internal override void InsertItem(int index, JToken item, bool skipParentCheck) + internal override void InsertItem(int index, JToken? item, bool skipParentCheck) { // don't add comments to JObject, no name to reference comment by if (item != null && item.Type == JTokenType.Comment) @@ -139,7 +146,7 @@ internal override void InsertItem(int index, JToken item, bool skipParentCheck) base.InsertItem(index, item, skipParentCheck); } - internal override void ValidateToken(JToken o, JToken existing) + internal override void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, nameof(o)); @@ -166,16 +173,16 @@ internal override void ValidateToken(JToken o, JToken existing) } } - internal override void MergeItem(object content, JsonMergeSettings settings) + internal override void MergeItem(object content, JsonMergeSettings? settings) { if (!(content is JObject o)) { return; } - foreach (KeyValuePair contentItem in o) + foreach (KeyValuePair contentItem in o) { - JProperty existingProperty = Property(contentItem.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); + JProperty? existingProperty = Property(contentItem.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); if (existingProperty == null) { @@ -262,7 +269,7 @@ public IEnumerable Properties() /// /// The property name. /// A with the specified name or null. - public JProperty Property(string name) + public JProperty? Property(string name) { return Property(name, StringComparison.Ordinal); } @@ -275,14 +282,14 @@ public JProperty Property(string name) /// The property name. /// One of the enumeration values that specifies how the strings will be compared. /// A matched with the specified name or null. - public JProperty Property(string name, StringComparison comparison) + public JProperty? Property(string name, StringComparison comparison) { if (name == null) { return null; } - if (_properties.TryGetValue(name, out JToken property)) + if (_properties.TryGetValue(name, out JToken? property)) { return (JProperty)property; } @@ -316,7 +323,7 @@ public JEnumerable PropertyValues() /// Gets the with the specified key. /// /// The with the specified key. - public override JToken this[object key] + public override JToken? this[object key] { get { @@ -346,29 +353,29 @@ public override JToken this[object key] /// Gets or sets the with the specified property name. /// /// - public JToken this[string propertyName] + public JToken? this[string propertyName] { get { ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName)); - JProperty property = Property(propertyName, StringComparison.Ordinal); + JProperty? property = Property(propertyName, StringComparison.Ordinal); return property?.Value; } set { - JProperty property = Property(propertyName, StringComparison.Ordinal); + JProperty? property = Property(propertyName, StringComparison.Ordinal); if (property != null) { - property.Value = value; + property.Value = value!; } else { #if HAVE_INOTIFY_PROPERTY_CHANGING OnPropertyChanging(propertyName); #endif - Add(new JProperty(propertyName, value)); + Add(propertyName, value); OnPropertyChanged(propertyName); } } @@ -397,7 +404,7 @@ public JToken this[string propertyName] /// /// is not valid JSON. /// - public new static JObject Load(JsonReader reader, JsonLoadSettings settings) + public new static JObject Load(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); @@ -453,7 +460,7 @@ public JToken this[string propertyName] /// /// /// - public new static JObject Parse(string json, JsonLoadSettings settings) + public new static JObject Parse(string json, JsonLoadSettings? settings) { using (JsonReader reader = new JsonTextReader(new StringReader(json))) { @@ -488,7 +495,7 @@ public JToken this[string propertyName] { JToken token = FromObjectInternal(o, jsonSerializer); - if (token != null && token.Type != JTokenType.Object) + if (token.Type != JTokenType.Object) { throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } @@ -518,7 +525,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter /// /// Name of the property. /// The with the specified property name. - public JToken GetValue(string propertyName) + public JToken? GetValue(string? propertyName) { return GetValue(propertyName, StringComparison.Ordinal); } @@ -531,7 +538,7 @@ public JToken GetValue(string propertyName) /// Name of the property. /// One of the enumeration values that specifies how the strings will be compared. /// The with the specified property name. - public JToken GetValue(string propertyName, StringComparison comparison) + public JToken? GetValue(string? propertyName, StringComparison comparison) { if (propertyName == null) { @@ -553,7 +560,7 @@ public JToken GetValue(string propertyName, StringComparison comparison) /// The value. /// One of the enumeration values that specifies how the strings will be compared. /// true if a value was successfully retrieved; otherwise, false. - public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value) + public bool TryGetValue(string propertyName, StringComparison comparison, [NotNullWhen(true)]out JToken? value) { value = GetValue(propertyName, comparison); return (value != null); @@ -565,7 +572,7 @@ public bool TryGetValue(string propertyName, StringComparison comparison, out JT /// /// Name of the property. /// The value. - public void Add(string propertyName, JToken value) + public void Add(string propertyName, JToken? value) { Add(new JProperty(propertyName, value)); } @@ -582,7 +589,7 @@ public bool ContainsKey(string propertyName) return _properties.Contains(propertyName); } - ICollection IDictionary.Keys => _properties.Keys; + ICollection IDictionary.Keys => _properties.Keys; /// /// Removes the property with the specified name. @@ -591,7 +598,7 @@ public bool ContainsKey(string propertyName) /// true if item was successfully removed; otherwise, false. public bool Remove(string propertyName) { - JProperty property = Property(propertyName, StringComparison.Ordinal); + JProperty? property = Property(propertyName, StringComparison.Ordinal); if (property == null) { return false; @@ -607,9 +614,9 @@ public bool Remove(string propertyName) /// Name of the property. /// The value. /// true if a value was successfully retrieved; otherwise, false. - public bool TryGetValue(string propertyName, out JToken value) + public bool TryGetValue(string propertyName, [NotNullWhen(true)]out JToken? value) { - JProperty property = Property(propertyName, StringComparison.Ordinal); + JProperty? property = Property(propertyName, StringComparison.Ordinal); if (property == null) { value = null; @@ -620,24 +627,24 @@ public bool TryGetValue(string propertyName, out JToken value) return true; } - ICollection IDictionary.Values => throw new NotImplementedException(); + ICollection IDictionary.Values => throw new NotImplementedException(); #endregion #region ICollection> Members - void ICollection>.Add(KeyValuePair item) + void ICollection>.Add(KeyValuePair item) { Add(new JProperty(item.Key, item.Value)); } - void ICollection>.Clear() + void ICollection>.Clear() { RemoveAll(); } - bool ICollection>.Contains(KeyValuePair item) + bool ICollection>.Contains(KeyValuePair item) { - JProperty property = Property(item.Key, StringComparison.Ordinal); + JProperty? property = Property(item.Key, StringComparison.Ordinal); if (property == null) { return false; @@ -646,7 +653,7 @@ bool ICollection>.Contains(KeyValuePair>.CopyTo(KeyValuePair[] array, int arrayIndex) + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) { @@ -668,16 +675,16 @@ void ICollection>.CopyTo(KeyValuePair(property.Name, property.Value); + array[arrayIndex + index] = new KeyValuePair(property.Name, property.Value); index++; } } - bool ICollection>.IsReadOnly => false; + bool ICollection>.IsReadOnly => false; - bool ICollection>.Remove(KeyValuePair item) + bool ICollection>.Remove(KeyValuePair item) { - if (!((ICollection>)this).Contains(item)) + if (!((ICollection>)this).Contains(item)) { return false; } @@ -698,11 +705,11 @@ internal override int GetDeepHashCode() /// /// A that can be used to iterate through the collection. /// - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() { foreach (JProperty property in _properties) { - yield return new KeyValuePair(property.Name, property.Value); + yield return new KeyValuePair(property.Name, property.Value); } } @@ -739,7 +746,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] att { PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null); - foreach (KeyValuePair propertyValue in this) + foreach (KeyValuePair propertyValue in this) { descriptors.Add(new JPropertyDescriptor(propertyValue.Key)); } @@ -752,12 +759,12 @@ AttributeCollection ICustomTypeDescriptor.GetAttributes() return AttributeCollection.Empty; } - string ICustomTypeDescriptor.GetClassName() + string? ICustomTypeDescriptor.GetClassName() { return null; } - string ICustomTypeDescriptor.GetComponentName() + string? ICustomTypeDescriptor.GetComponentName() { return null; } @@ -767,17 +774,17 @@ TypeConverter ICustomTypeDescriptor.GetConverter() return new TypeConverter(); } - EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() + EventDescriptor? ICustomTypeDescriptor.GetDefaultEvent() { return null; } - PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() + PropertyDescriptor? ICustomTypeDescriptor.GetDefaultProperty() { return null; } - object ICustomTypeDescriptor.GetEditor(Type editorBaseType) + object? ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return null; } @@ -792,7 +799,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() return EventDescriptorCollection.Empty; } - object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) + object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { if (pd is JPropertyDescriptor) { @@ -820,7 +827,7 @@ protected override DynamicMetaObject GetMetaObject(Expression parameter) private class JObjectDynamicProxy : DynamicProxy { - public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object result) + public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object? result) { // result can be null result = instance[binder.Name]; diff --git a/Src/Newtonsoft.Json/Linq/JProperty.Async.cs b/Src/Newtonsoft.Json/Linq/JProperty.Async.cs index 9083a9850..dcd7cb3b1 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.Async.cs @@ -88,7 +88,7 @@ private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationTo /// The token to monitor for cancellation requests. The default value is . /// A representing the asynchronous creation. The /// property returns a that contains the JSON that was read from the specified . - public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { if (reader.TokenType == JsonToken.None) { @@ -105,7 +105,7 @@ private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationTo throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - JProperty p = new JProperty((string)reader.Value); + JProperty p = new JProperty((string)reader.Value!); p.SetLineInfo(reader as IJsonLineInfo, settings); await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs index ab938a9b7..5e2b998c5 100644 --- a/Src/Newtonsoft.Json/Linq/JProperty.cs +++ b/Src/Newtonsoft.Json/Linq/JProperty.cs @@ -40,7 +40,7 @@ public partial class JProperty : JContainer #region JPropertyList private class JPropertyList : IList { - internal JToken _token; + internal JToken? _token; public IEnumerator GetEnumerator() { @@ -115,13 +115,24 @@ public void RemoveAt(int index) public JToken this[int index] { - get => (index == 0) ? _token : null; + get + { + if (index != 0) + { + throw new IndexOutOfRangeException(); + } + + Debug.Assert(_token != null); + return _token; + } set { - if (index == 0) + if (index != 0) { - _token = value; + throw new IndexOutOfRangeException(); } + + _token = value; } } } @@ -153,7 +164,7 @@ public string Name public JToken Value { [DebuggerStepThrough] - get { return _content._token; } + get { return _content._token!; } set { CheckReentrancy(); @@ -191,7 +202,7 @@ internal override JToken GetItem(int index) return Value; } - internal override void SetItem(int index, JToken item) + internal override void SetItem(int index, JToken? item) { if (index != 0) { @@ -203,14 +214,14 @@ internal override void SetItem(int index, JToken item) return; } - ((JObject)Parent)?.InternalPropertyChanging(this); + ((JObject?)Parent)?.InternalPropertyChanging(this); base.SetItem(0, item); - ((JObject)Parent)?.InternalPropertyChanged(this); + ((JObject?)Parent)?.InternalPropertyChanged(this); } - internal override bool RemoveItem(JToken item) + internal override bool RemoveItem(JToken? item) { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } @@ -220,12 +231,17 @@ internal override void RemoveItemAt(int index) throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } - internal override int IndexOfItem(JToken item) + internal override int IndexOfItem(JToken? item) { + if (item == null) + { + return -1; + } + return _content.IndexOf(item); } - internal override void InsertItem(int index, JToken item, bool skipParentCheck) + internal override void InsertItem(int index, JToken? item, bool skipParentCheck) { // don't add comments to JProperty if (item != null && item.Type == JTokenType.Comment) @@ -241,14 +257,14 @@ internal override void InsertItem(int index, JToken item, bool skipParentCheck) base.InsertItem(0, item, false); } - internal override bool ContainsItem(JToken item) + internal override bool ContainsItem(JToken? item) { return (Value == item); } - internal override void MergeItem(object content, JsonMergeSettings settings) + internal override void MergeItem(object content, JsonMergeSettings? settings) { - JToken value = (content as JProperty)?.Value; + JToken? value = (content as JProperty)?.Value; if (value != null && value.Type != JTokenType.Null) { @@ -304,7 +320,7 @@ public JProperty(string name, params object[] content) /// /// The property name. /// The property content. - public JProperty(string name, object content) + public JProperty(string name, object? content) { ValidationUtils.ArgumentNotNull(name, nameof(name)); @@ -357,7 +373,7 @@ internal override int GetDeepHashCode() /// The used to load the JSON. /// If this is null, default load settings will be used. /// A that contains the JSON that was read from the specified . - public new static JProperty Load(JsonReader reader, JsonLoadSettings settings) + public new static JProperty Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None) { @@ -374,7 +390,7 @@ internal override int GetDeepHashCode() throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - JProperty p = new JProperty((string)reader.Value); + JProperty p = new JProperty((string)reader.Value!); p.SetLineInfo(reader as IJsonLineInfo, settings); p.ReadTokenFrom(reader, settings); diff --git a/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs b/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs index 08858c038..72ea02070 100644 --- a/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs +++ b/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs @@ -67,7 +67,7 @@ public override bool CanResetValue(object component) /// The value of a property for a given component. /// /// The component with the property for which to retrieve the value. - public override object GetValue(object component) + public override object? GetValue(object component) { return (component as JObject)?[Name]; } diff --git a/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs b/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs index 435e45738..1c4c186bc 100644 --- a/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs +++ b/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs @@ -26,6 +26,8 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Linq @@ -34,7 +36,7 @@ internal class JPropertyKeyedCollection : Collection { private static readonly IEqualityComparer Comparer = StringComparer.Ordinal; - private Dictionary _dictionary; + private Dictionary? _dictionary; public JPropertyKeyedCollection() : base(new List()) { @@ -43,7 +45,7 @@ public JPropertyKeyedCollection() : base(new List()) private void AddKey(string key, JToken item) { EnsureDictionary(); - _dictionary[key] = item; + _dictionary![key] = item; } protected void ChangeItemKey(JToken item, string newKey) @@ -189,7 +191,7 @@ public JToken this[string key] } } - public bool TryGetValue(string key, out JToken value) + public bool TryGetValue(string key, [NotNullWhen(true)]out JToken? value) { if (_dictionary == null) { @@ -205,7 +207,7 @@ public ICollection Keys get { EnsureDictionary(); - return _dictionary.Keys; + return _dictionary!.Keys; } } @@ -214,7 +216,7 @@ public ICollection Values get { EnsureDictionary(); - return _dictionary.Values; + return _dictionary!.Values; } } @@ -232,8 +234,8 @@ public bool Compare(JPropertyKeyedCollection other) // dictionaries in JavaScript aren't ordered // ignore order when comparing properties - Dictionary d1 = _dictionary; - Dictionary d2 = other._dictionary; + Dictionary? d1 = _dictionary; + Dictionary? d2 = other._dictionary; if (d1 == null && d2 == null) { @@ -242,7 +244,7 @@ public bool Compare(JPropertyKeyedCollection other) if (d1 == null) { - return (d2.Count == 0); + return (d2!.Count == 0); } if (d2 == null) diff --git a/Src/Newtonsoft.Json/Linq/JRaw.cs b/Src/Newtonsoft.Json/Linq/JRaw.cs index 9acc240f0..02ca51fd1 100644 --- a/Src/Newtonsoft.Json/Linq/JRaw.cs +++ b/Src/Newtonsoft.Json/Linq/JRaw.cs @@ -46,7 +46,7 @@ public JRaw(JRaw other) /// Initializes a new instance of the class. /// /// The raw json. - public JRaw(object rawJson) + public JRaw(object? rawJson) : base(rawJson, JTokenType.Raw) { } diff --git a/Src/Newtonsoft.Json/Linq/JToken.Async.cs b/Src/Newtonsoft.Json/Linq/JToken.Async.cs index 1d89e0fdc..4d147c2d8 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.Async.cs @@ -89,7 +89,7 @@ public static Task ReadFromAsync(JsonReader reader, CancellationToken ca /// that were read from the reader. The runtime type of the token is determined /// by the token type of the first token encountered in the reader. /// - public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); @@ -101,7 +101,7 @@ public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettin } } - IJsonLineInfo lineInfo = reader as IJsonLineInfo; + IJsonLineInfo? lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { @@ -123,7 +123,7 @@ public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettin v.SetLineInfo(lineInfo, settings); return v; case JsonToken.Comment: - v = JValue.CreateComment(reader.Value.ToString()); + v = JValue.CreateComment(reader.Value?.ToString()); v.SetLineInfo(lineInfo, settings); return v; case JsonToken.Null: @@ -168,7 +168,7 @@ public static Task LoadAsync(JsonReader reader, CancellationToken cancel /// that were read from the reader. The runtime type of the token is determined /// by the token type of the first token encountered in the reader. /// - public static Task LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default) + public static Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) { return ReadFromAsync(reader, settings, cancellationToken); } diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 05f641c1d..2db501b77 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -38,11 +38,12 @@ using System.Diagnostics; using System.Globalization; using System.Collections; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; - #endif namespace Newtonsoft.Json.Linq @@ -60,10 +61,10 @@ public abstract partial class JToken : IJEnumerable, IJsonLineInfo { private static JTokenEqualityComparer _equalityComparer; - private JContainer _parent; - private JToken _previous; - private JToken _next; - private object _annotations; + private JContainer? _parent; + private JToken? _previous; + private JToken? _next; + private object? _annotations; private static readonly JTokenType[] BooleanTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] NumberTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; @@ -99,7 +100,7 @@ public static JTokenEqualityComparer EqualityComparer /// Gets or sets the parent. /// /// The parent. - public JContainer Parent + public JContainer? Parent { [DebuggerStepThrough] get { return _parent; } @@ -114,7 +115,7 @@ public JToken Root { get { - JContainer parent = Parent; + JContainer? parent = Parent; if (parent == null) { return this; @@ -161,7 +162,7 @@ public static bool DeepEquals(JToken t1, JToken t2) /// Gets the next sibling token of this node. /// /// The that contains the next sibling token. - public JToken Next + public JToken? Next { get => _next; internal set => _next = value; @@ -171,7 +172,7 @@ public JToken Next /// Gets the previous sibling token of this node. /// /// The that contains the previous sibling token. - public JToken Previous + public JToken? Previous { get => _previous; internal set => _previous = value; @@ -190,8 +191,8 @@ public string Path } List positions = new List(); - JToken previous = null; - for (JToken current = this; current != null; current = current.Parent) + JToken? previous = null; + for (JToken? current = this; current != null; current = current.Parent) { switch (current.Type) { @@ -277,7 +278,7 @@ public IEnumerable AncestorsAndSelf() internal IEnumerable GetAncestors(bool self) { - for (JToken current = self ? this : Parent; current != null; current = current.Parent) + for (JToken? current = self ? this : Parent; current != null; current = current.Parent) { yield return current; } @@ -294,7 +295,7 @@ public IEnumerable AfterSelf() yield break; } - for (JToken o = Next; o != null; o = o.Next) + for (JToken? o = Next; o != null; o = o.Next) { yield return o; } @@ -306,7 +307,12 @@ public IEnumerable AfterSelf() /// A collection of the sibling tokens before this token, in document order. public IEnumerable BeforeSelf() { - for (JToken o = Parent.First; o != this; o = o.Next) + if (Parent == null) + { + yield break; + } + + for (JToken? o = Parent.First; o != this && o != null; o = o.Next) { yield return o; } @@ -316,7 +322,7 @@ public IEnumerable BeforeSelf() /// Gets the with the specified key. /// /// The with the specified key. - public virtual JToken this[object key] + public virtual JToken? this[object key] { get => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); set => throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); @@ -330,7 +336,7 @@ public virtual JToken this[object key] /// The converted token value. public virtual T Value(object key) { - JToken token = this[key]; + JToken? token = this[key]; // null check to fix MonoTouch issue - https://github.com/dolbz/Newtonsoft.Json/commit/a24e3062846b30ee505f3271ac08862bb471b822 return token == null ? default : Extensions.Convert(token); @@ -340,13 +346,13 @@ public virtual T Value(object key) /// Get the first child token of this token. /// /// A containing the first child token of the . - public virtual JToken First => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); + public virtual JToken? First => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); /// /// Get the last child token of this token. /// /// A containing the last child token of the . - public virtual JToken Last => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); + public virtual JToken? Last => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); /// /// Returns a collection of the child tokens of this token, in document order. @@ -441,7 +447,7 @@ public string ToString(Formatting formatting, params JsonConverter[] converters) } } - private static JValue EnsureValue(JToken value) + private static JValue? EnsureValue(JToken value) { if (value == null) { @@ -453,7 +459,7 @@ private static JValue EnsureValue(JToken value) value = property.Value; } - JValue v = value as JValue; + JValue? v = value as JValue; return v; } @@ -483,7 +489,7 @@ private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullab /// The result of the conversion. public static explicit operator bool(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, BooleanTypes, false)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -507,7 +513,7 @@ public static explicit operator bool(JToken value) /// The result of the conversion. public static explicit operator DateTimeOffset(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, DateTimeTypes, false)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -539,7 +545,7 @@ public static explicit operator DateTimeOffset(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, BooleanTypes, true)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -562,7 +568,7 @@ public static explicit operator DateTimeOffset(JToken value) /// The result of the conversion. public static explicit operator long(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -590,7 +596,7 @@ public static explicit operator long(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, DateTimeTypes, true)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -619,7 +625,7 @@ public static explicit operator long(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, DateTimeTypes, true)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -655,7 +661,7 @@ public static explicit operator long(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -683,7 +689,7 @@ public static explicit operator long(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -711,7 +717,7 @@ public static explicit operator long(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, CharTypes, true)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -734,7 +740,7 @@ public static explicit operator long(JToken value) /// The result of the conversion. public static explicit operator int(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -757,7 +763,7 @@ public static explicit operator int(JToken value) /// The result of the conversion. public static explicit operator short(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -781,7 +787,7 @@ public static explicit operator short(JToken value) [CLSCompliant(false)] public static explicit operator ushort(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -805,7 +811,7 @@ public static explicit operator ushort(JToken value) [CLSCompliant(false)] public static explicit operator char(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, CharTypes, false)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -828,7 +834,7 @@ public static explicit operator char(JToken value) /// The result of the conversion. public static explicit operator byte(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -852,7 +858,7 @@ public static explicit operator byte(JToken value) [CLSCompliant(false)] public static explicit operator sbyte(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -880,7 +886,7 @@ public static explicit operator sbyte(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -908,7 +914,7 @@ public static explicit operator sbyte(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -937,7 +943,7 @@ public static explicit operator sbyte(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -965,7 +971,7 @@ public static explicit operator sbyte(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -994,7 +1000,7 @@ public static explicit operator sbyte(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1017,7 +1023,7 @@ public static explicit operator sbyte(JToken value) /// The result of the conversion. public static explicit operator DateTime(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, DateTimeTypes, false)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1045,7 +1051,7 @@ public static explicit operator DateTime(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1073,7 +1079,7 @@ public static explicit operator DateTime(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1096,7 +1102,7 @@ public static explicit operator DateTime(JToken value) /// The result of the conversion. public static explicit operator decimal(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1125,7 +1131,7 @@ public static explicit operator decimal(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1154,7 +1160,7 @@ public static explicit operator decimal(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, true)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1177,7 +1183,7 @@ public static explicit operator decimal(JToken value) /// The result of the conversion. public static explicit operator double(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1200,7 +1206,7 @@ public static explicit operator double(JToken value) /// The result of the conversion. public static explicit operator float(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1221,14 +1227,14 @@ public static explicit operator float(JToken value) /// /// The value. /// The result of the conversion. - public static explicit operator string(JToken value) + public static explicit operator string?(JToken value) { if (value == null) { return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, StringTypes, true)) { throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1262,7 +1268,7 @@ public static explicit operator string(JToken value) [CLSCompliant(false)] public static explicit operator uint(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1286,7 +1292,7 @@ public static explicit operator uint(JToken value) [CLSCompliant(false)] public static explicit operator ulong(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, NumberTypes, false)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1307,14 +1313,14 @@ public static explicit operator ulong(JToken value) /// /// The value. /// The result of the conversion. - public static explicit operator byte[](JToken value) + public static explicit operator byte[]?(JToken value) { if (value == null) { return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, BytesTypes, false)) { throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1346,7 +1352,7 @@ public static explicit operator byte[](JToken value) /// The result of the conversion. public static explicit operator Guid(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, GuidTypes, false)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1372,7 +1378,7 @@ public static explicit operator Guid(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, GuidTypes, true)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1398,7 +1404,7 @@ public static explicit operator Guid(JToken value) /// The result of the conversion. public static explicit operator TimeSpan(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, TimeSpanTypes, false)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1419,7 +1425,7 @@ public static explicit operator TimeSpan(JToken value) return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, TimeSpanTypes, true)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1438,14 +1444,14 @@ public static explicit operator TimeSpan(JToken value) /// /// The value. /// The result of the conversion. - public static explicit operator Uri(JToken value) + public static explicit operator Uri?(JToken value) { if (value == null) { return null; } - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, UriTypes, true)) { throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1462,18 +1468,18 @@ public static explicit operator Uri(JToken value) #if HAVE_BIG_INTEGER private static BigInteger ToBigInteger(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, BigIntegerTypes, false)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } - return ConvertUtils.ToBigInteger(v.Value); + return ConvertUtils.ToBigInteger(v.Value!); } private static BigInteger? ToBigIntegerNullable(JToken value) { - JValue v = EnsureValue(value); + JValue? v = EnsureValue(value); if (v == null || !ValidateToken(v, BigIntegerTypes, true)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); @@ -1867,7 +1873,7 @@ IEnumerator IEnumerable.GetEnumerator() internal abstract int GetDeepHashCode(); - IJEnumerable IJEnumerable.this[object key] => this[key]; + IJEnumerable IJEnumerable.this[object key] => this[key]!; /// /// Creates a for this token. @@ -1887,7 +1893,7 @@ internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerialize using (JTokenWriter jsonWriter = new JTokenWriter()) { jsonSerializer.Serialize(jsonWriter, o); - token = jsonWriter.Token; + token = jsonWriter.Token!; } return token; @@ -1919,9 +1925,12 @@ public static JToken FromObject(object o, JsonSerializer jsonSerializer) /// /// The object type that the token will be deserialized to. /// The new object created from the JSON value. + [return: MaybeNull] public T ToObject() { +#pragma warning disable CS8601 // Possible null reference assignment. return (T)ToObject(typeof(T)); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -1929,7 +1938,7 @@ public T ToObject() /// /// The object type that the token will be deserialized to. /// The new object created from the JSON value. - public object ToObject(Type objectType) + public object? ToObject(Type objectType) { if (JsonConvert.DefaultSettings == null) { @@ -1947,7 +1956,7 @@ public object ToObject(Type objectType) catch (Exception ex) { Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType); - throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string)this, enumType.Name), ex); + throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string?)this, enumType.Name), ex); } } @@ -2023,13 +2032,13 @@ public object ToObject(Type objectType) return (DateTimeOffset)this; #endif case PrimitiveTypeCode.String: - return (string)this; + return (string?)this; case PrimitiveTypeCode.GuidNullable: return (Guid?)this; case PrimitiveTypeCode.Guid: return (Guid)this; case PrimitiveTypeCode.Uri: - return (Uri)this; + return (Uri?)this; case PrimitiveTypeCode.TimeSpanNullable: return (TimeSpan?)this; case PrimitiveTypeCode.TimeSpan: @@ -2052,9 +2061,12 @@ public object ToObject(Type objectType) /// The object type that the token will be deserialized to. /// The that will be used when creating the object. /// The new object created from the JSON value. + [return: MaybeNull] public T ToObject(JsonSerializer jsonSerializer) { +#pragma warning disable CS8601 // Possible null reference assignment. return (T)ToObject(typeof(T), jsonSerializer); +#pragma warning restore CS8601 // Possible null reference assignment. } /// @@ -2063,7 +2075,7 @@ public T ToObject(JsonSerializer jsonSerializer) /// The object type that the token will be deserialized to. /// The that will be used when creating the object. /// The new object created from the JSON value. - public object ToObject(Type objectType, JsonSerializer jsonSerializer) + public object? ToObject(Type objectType, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer)); @@ -2098,7 +2110,7 @@ public static JToken ReadFrom(JsonReader reader) /// that were read from the reader. The runtime type of the token is determined /// by the token type of the first token encountered in the reader. /// - public static JToken ReadFrom(JsonReader reader, JsonLoadSettings settings) + public static JToken ReadFrom(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); @@ -2123,7 +2135,7 @@ public static JToken ReadFrom(JsonReader reader, JsonLoadSettings settings) throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); } - IJsonLineInfo lineInfo = reader as IJsonLineInfo; + IJsonLineInfo? lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { @@ -2145,7 +2157,7 @@ public static JToken ReadFrom(JsonReader reader, JsonLoadSettings settings) v.SetLineInfo(lineInfo, settings); return v; case JsonToken.Comment: - v = JValue.CreateComment(reader.Value.ToString()); + v = JValue.CreateComment(reader.Value!.ToString()); v.SetLineInfo(lineInfo, settings); return v; case JsonToken.Null: @@ -2178,7 +2190,7 @@ public static JToken Parse(string json) /// The used to load the JSON. /// If this is null, default load settings will be used. /// A populated from the string that contains JSON. - public static JToken Parse(string json, JsonLoadSettings settings) + public static JToken Parse(string json, JsonLoadSettings? settings) { using (JsonReader reader = new JsonTextReader(new StringReader(json))) { @@ -2189,7 +2201,6 @@ public static JToken Parse(string json, JsonLoadSettings settings) // Any content encountered here other than a comment will throw in the reader. } - return t; } } @@ -2205,7 +2216,7 @@ public static JToken Parse(string json, JsonLoadSettings settings) /// that were read from the reader. The runtime type of the token is determined /// by the token type of the first token encountered in the reader. /// - public static JToken Load(JsonReader reader, JsonLoadSettings settings) + public static JToken Load(JsonReader reader, JsonLoadSettings? settings) { return ReadFrom(reader, settings); } @@ -2224,7 +2235,7 @@ public static JToken Load(JsonReader reader) return Load(reader, null); } - internal void SetLineInfo(IJsonLineInfo lineInfo, JsonLoadSettings settings) + internal void SetLineInfo(IJsonLineInfo? lineInfo, JsonLoadSettings? settings) { if (settings != null && settings.LineInfoHandling != LineInfoHandling.Load) { @@ -2265,7 +2276,7 @@ int IJsonLineInfo.LineNumber { get { - LineInfoAnnotation annotation = Annotation(); + LineInfoAnnotation? annotation = Annotation(); if (annotation != null) { return annotation.LineNumber; @@ -2279,7 +2290,7 @@ int IJsonLineInfo.LinePosition { get { - LineInfoAnnotation annotation = Annotation(); + LineInfoAnnotation? annotation = Annotation(); if (annotation != null) { return annotation.LinePosition; @@ -2296,7 +2307,7 @@ int IJsonLineInfo.LinePosition /// A that contains a JPath expression. /// /// A , or null. - public JToken SelectToken(string path) + public JToken? SelectToken(string path) { return SelectToken(path, false); } @@ -2309,11 +2320,11 @@ public JToken SelectToken(string path) /// /// A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. /// A . - public JToken SelectToken(string path, bool errorWhenNoMatch) + public JToken? SelectToken(string path, bool errorWhenNoMatch) { JPath p = new JPath(path); - JToken token = null; + JToken? token = null; foreach (JToken t in p.Evaluate(this, this, errorWhenNoMatch)) { if (token != null) @@ -2438,7 +2449,7 @@ public void AddAnnotation(object annotation) /// /// The type of the annotation to retrieve. /// The first annotation object that matches the specified type, or null if no annotation is of the specified type. - public T Annotation() where T : class + public T? Annotation() where T : class { if (_annotations != null) { @@ -2469,7 +2480,7 @@ public T Annotation() where T : class /// /// The of the annotation to retrieve. /// The first annotation object that matches the specified type, or null if no annotation is of the specified type. - public object Annotation(Type type) + public object? Annotation(Type type) { if (type == null) { @@ -2595,7 +2606,7 @@ public void RemoveAnnotations() where T : class { if (_annotations != null) { - if (!(_annotations is object[] annotations)) + if (!(_annotations is object?[] annotations)) { if (_annotations is T) { @@ -2608,7 +2619,7 @@ public void RemoveAnnotations() where T : class int keepCount = 0; while (index < annotations.Length) { - object obj2 = annotations[index]; + object? obj2 = annotations[index]; if (obj2 == null) { break; @@ -2650,7 +2661,7 @@ public void RemoveAnnotations(Type type) if (_annotations != null) { - if (!(_annotations is object[] annotations)) + if (!(_annotations is object?[] annotations)) { if (type.IsInstanceOfType(_annotations)) { @@ -2663,7 +2674,7 @@ public void RemoveAnnotations(Type type) int keepCount = 0; while (index < annotations.Length) { - object o = annotations[index]; + object? o = annotations[index]; if (o == null) { break; diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index 7a97705cb..aad1150c1 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -34,14 +34,14 @@ namespace Newtonsoft.Json.Linq public class JTokenReader : JsonReader, IJsonLineInfo { private readonly JToken _root; - private string _initialPath; - private JToken _parent; - private JToken _current; + private string? _initialPath; + private JToken? _parent; + private JToken? _current; /// /// Gets the at the reader's current position. /// - public JToken CurrentToken => _current; + public JToken? CurrentToken => _current; /// /// Initializes a new instance of the class. @@ -102,8 +102,8 @@ private bool ReadOver(JToken t) return ReadToEnd(); } - JToken next = t.Next; - if ((next == null || next == t) || t == t.Parent.Last) + JToken? next = t.Next; + if ((next == null || next == t) || t == t.Parent!.Last) { if (t.Parent == null) { @@ -146,7 +146,7 @@ private bool ReadToEnd() private bool ReadInto(JContainer c) { - JToken firstChild = c.First; + JToken? firstChild = c.First; if (firstChild == null) { return SetEnd(c); @@ -215,7 +215,7 @@ private void SetToken(JToken token) break; case JTokenType.Date: { - object v = ((JValue)token).Value; + object? v = ((JValue)token).Value; if (v is DateTime dt) { v = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); @@ -235,7 +235,7 @@ private void SetToken(JToken token) break; case JTokenType.Uri: { - object v = ((JValue)token).Value; + object? v = ((JValue)token).Value; SetToken(JsonToken.String, v is Uri uri ? uri.OriginalString : SafeToString(v)); break; } @@ -247,7 +247,7 @@ private void SetToken(JToken token) } } - private string SafeToString(object value) + private string? SafeToString(object? value) { return value?.ToString(); } @@ -259,7 +259,7 @@ bool IJsonLineInfo.HasLineInfo() return false; } - IJsonLineInfo info = _current; + IJsonLineInfo? info = _current; return (info != null && info.HasLineInfo()); } @@ -272,7 +272,7 @@ int IJsonLineInfo.LineNumber return 0; } - IJsonLineInfo info = _current; + IJsonLineInfo? info = _current; if (info != null) { return info.LineNumber; @@ -291,7 +291,7 @@ int IJsonLineInfo.LinePosition return 0; } - IJsonLineInfo info = _current; + IJsonLineInfo? info = _current; if (info != null) { return info.LinePosition; diff --git a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs index 3c8230175..f49169e9e 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Diagnostics; using System.Globalization; #if HAVE_BIG_INTEGER using System.Numerics; @@ -37,22 +38,22 @@ namespace Newtonsoft.Json.Linq /// public partial class JTokenWriter : JsonWriter { - private JContainer _token; - private JContainer _parent; + private JContainer? _token; + private JContainer? _parent; // used when writer is writing single value and the value has no containing parent - private JValue _value; - private JToken _current; + private JValue? _value; + private JToken? _current; /// /// Gets the at the writer's current position. /// - public JToken CurrentToken => _current; + public JToken? CurrentToken => _current; /// /// Gets the token being written. /// /// The token being written. - public JToken Token + public JToken? Token { get { @@ -131,7 +132,7 @@ private void AddParent(JContainer container) private void RemoveParent() { _current = _parent; - _parent = _parent.Parent; + _parent = _parent!.Parent; if (_parent != null && _parent.Type == JTokenType.Property) { @@ -186,12 +187,12 @@ public override void WritePropertyName(string name) base.WritePropertyName(name); } - private void AddValue(object value, JsonToken token) + private void AddValue(object? value, JsonToken token) { AddValue(new JValue(value), token); } - internal void AddValue(JValue value, JsonToken token) + internal void AddValue(JValue? value, JsonToken token) { if (_parent != null) { @@ -216,7 +217,7 @@ internal void AddValue(JValue value, JsonToken token) /// An error will be raised if the value cannot be written as a single JSON token. /// /// The value to write. - public override void WriteValue(object value) + public override void WriteValue(object? value) { #if HAVE_BIG_INTEGER if (value is BigInteger) @@ -253,7 +254,7 @@ public override void WriteUndefined() /// Writes raw JSON. /// /// The raw JSON to write. - public override void WriteRaw(string json) + public override void WriteRaw(string? json) { base.WriteRaw(json); AddValue(new JRaw(json), JsonToken.Raw); @@ -263,7 +264,7 @@ public override void WriteRaw(string json) /// Writes a comment /*...*/ containing the specified text. /// /// Text to place inside the comment. - public override void WriteComment(string text) + public override void WriteComment(string? text) { base.WriteComment(text); AddValue(JValue.CreateComment(text), JsonToken.Comment); @@ -273,7 +274,7 @@ public override void WriteComment(string text) /// Writes a value. /// /// The value to write. - public override void WriteValue(string value) + public override void WriteValue(string? value) { base.WriteValue(value); AddValue(value, JsonToken.String); @@ -446,7 +447,7 @@ public override void WriteValue(DateTimeOffset value) /// Writes a [] value. /// /// The [] value to write. - public override void WriteValue(byte[] value) + public override void WriteValue(byte[]? value) { base.WriteValue(value); AddValue(value, JsonToken.Bytes); @@ -476,7 +477,7 @@ public override void WriteValue(Guid value) /// Writes a value. /// /// The value to write. - public override void WriteValue(Uri value) + public override void WriteValue(Uri? value) { base.WriteValue(value); AddValue(value, JsonToken.String); @@ -496,7 +497,7 @@ internal override void WriteToken(JsonReader reader, bool writeChildren, bool wr } } - JToken value = tokenReader.CurrentToken.CloneToken(); + JToken value = tokenReader.CurrentToken!.CloneToken(); if (_parent != null) { diff --git a/Src/Newtonsoft.Json/Linq/JValue.Async.cs b/Src/Newtonsoft.Json/Linq/JValue.Async.cs index 91402d107..e80b880a0 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.Async.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.Async.cs @@ -49,7 +49,7 @@ public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellat { if (converters != null && converters.Length > 0 && _value != null) { - JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); + JsonConverter? matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { // TODO: Call WriteJsonAsync when it exists. @@ -121,13 +121,13 @@ public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellat return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Bytes: - return writer.WriteValueAsync((byte[])_value, cancellationToken); + return writer.WriteValueAsync((byte[]?)_value, cancellationToken); case JTokenType.Guid: return writer.WriteValueAsync(_value != null ? (Guid?)_value : null, cancellationToken); case JTokenType.TimeSpan: return writer.WriteValueAsync(_value != null ? (TimeSpan?)_value : null, cancellationToken); case JTokenType.Uri: - return writer.WriteValueAsync((Uri)_value, cancellationToken); + return writer.WriteValueAsync((Uri?)_value, cancellationToken); } throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type."); diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 85e2473fd..fba0af289 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -28,6 +28,8 @@ using System.Diagnostics; using Newtonsoft.Json.Utilities; using System.Globalization; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if HAVE_DYNAMIC using System.Dynamic; using System.Linq.Expressions; @@ -47,9 +49,9 @@ public partial class JValue : JToken, IEquatable, IFormattable, ICompara #endif { private JTokenType _valueType; - private object _value; + private object? _value; - internal JValue(object value, JTokenType type) + internal JValue(object? value, JTokenType type) { _value = value; _valueType = type; @@ -188,7 +190,7 @@ public JValue(TimeSpan value) /// Initializes a new instance of the class with the given value. /// /// The value. - public JValue(object value) + public JValue(object? value) : this(value, GetValueType(null, value)) { } @@ -241,7 +243,7 @@ private static int CompareBigInteger(BigInteger i1, object i2) } #endif - internal static int Compare(JTokenType valueType, object objA, object objB) + internal static int Compare(JTokenType valueType, object? objA, object? objB) { if (objA == objB) { @@ -267,8 +269,8 @@ internal static int Compare(JTokenType valueType, object objA, object objB) } if (objB is BigInteger integerB) { - return -CompareBigInteger(integerB, objA); - } + return -CompareBigInteger(integerB, objA); + } #endif if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { @@ -300,7 +302,7 @@ internal static int Compare(JTokenType valueType, object objA, object objB) return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); } return CompareFloat(objA, objB); - } + } case JTokenType.Comment: case JTokenType.String: case JTokenType.Raw: @@ -353,10 +355,10 @@ internal static int Compare(JTokenType valueType, object objA, object objB) throw new ArgumentException("Object must be of type byte[]."); } - byte[] bytesA = objA as byte[]; + byte[]? bytesA = objA as byte[]; Debug.Assert(bytesA != null); - return MiscellaneousUtils.ByteArrayCompare(bytesA, bytesB); + return MiscellaneousUtils.ByteArrayCompare(bytesA!, bytesB); case JTokenType.Guid: if (!(objB is Guid)) { @@ -368,7 +370,7 @@ internal static int Compare(JTokenType valueType, object objA, object objB) return guid1.CompareTo(guid2); case JTokenType.Uri: - Uri uri2 = objB as Uri; + Uri? uri2 = objB as Uri; if (uri2 == null) { throw new ArgumentException("Object must be of type Uri."); @@ -407,7 +409,7 @@ private static int CompareFloat(object objA, object objB) } #if HAVE_EXPRESSIONS - private static bool Operation(ExpressionType operation, object objA, object objB, out object result) + private static bool Operation(ExpressionType operation, object? objA, object? objB, out object? result) { if (objA is string || objB is string) { @@ -564,7 +566,7 @@ internal override JToken CloneToken() /// /// The value. /// A comment with the given value. - public static JValue CreateComment(string value) + public static JValue CreateComment(string? value) { return new JValue(value, JTokenType.Comment); } @@ -597,7 +599,7 @@ public static JValue CreateUndefined() return new JValue(null, JTokenType.Undefined); } - private static JTokenType GetValueType(JTokenType? current, object value) + private static JTokenType GetValueType(JTokenType? current, object? value) { if (value == null) { @@ -694,13 +696,13 @@ private static JTokenType GetStringValueType(JTokenType? current) /// Gets or sets the underlying token value. /// /// The underlying token value. - public object Value + public object? Value { get => _value; set { - Type currentType = _value?.GetType(); - Type newType = value?.GetType(); + Type? currentType = _value?.GetType(); + Type? newType = value?.GetType(); if (currentType != newType) { @@ -720,7 +722,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter { if (converters != null && converters.Length > 0 && _value != null) { - JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); + JsonConverter? matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); @@ -803,7 +805,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter } return; case JTokenType.Bytes: - writer.WriteValue((byte[])_value); + writer.WriteValue((byte[]?)_value); return; case JTokenType.Guid: writer.WriteValue((_value != null) ? (Guid?)_value : null); @@ -812,7 +814,7 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter writer.WriteValue((_value != null) ? (TimeSpan?)_value : null); return; case JTokenType.Uri: - writer.WriteValue((Uri)_value); + writer.WriteValue((Uri?)_value); return; } @@ -839,7 +841,7 @@ private static bool ValuesEquals(JValue v1, JValue v2) /// true if the current object is equal to the parameter; otherwise, false. /// /// An object to compare with this object. - public bool Equals(JValue other) + public bool Equals([AllowNull] JValue other) { if (other == null) { @@ -858,7 +860,12 @@ public bool Equals(JValue other) /// public override bool Equals(object obj) { - return Equals(obj as JValue); + if (obj is JValue v) + { + return Equals(v); + } + + return false; } /// @@ -925,7 +932,7 @@ public string ToString(IFormatProvider formatProvider) /// /// A that represents this instance. /// - public string ToString(string format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider formatProvider) { if (_value == null) { @@ -957,7 +964,7 @@ protected override DynamicMetaObject GetMetaObject(Expression parameter) private class JValueDynamicProxy : DynamicProxy { - public override bool TryConvert(JValue instance, ConvertBinder binder, out object result) + public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)]out object? result) { if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken)) { @@ -965,7 +972,7 @@ public override bool TryConvert(JValue instance, ConvertBinder binder, out objec return true; } - object value = instance.Value; + object? value = instance.Value; if (value == null) { @@ -977,9 +984,9 @@ public override bool TryConvert(JValue instance, ConvertBinder binder, out objec return true; } - public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result) + public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, [NotNullWhen(true)]out object? result) { - object compareValue = arg is JValue value ? value.Value : arg; + object? compareValue = arg is JValue value ? value.Value : arg; switch (binder.Operation) { @@ -1031,7 +1038,7 @@ int IComparable.CompareTo(object obj) } JTokenType comparisonType; - object otherValue; + object? otherValue; if (obj is JValue value) { otherValue = value.Value; @@ -1166,7 +1173,7 @@ DateTime IConvertible.ToDateTime(IFormatProvider provider) return (DateTime)this; } - object IConvertible.ToType(Type conversionType, IFormatProvider provider) + object? IConvertible.ToType(Type conversionType, IFormatProvider provider) { return ToObject(conversionType); } diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs index c6cb1e889..653a2ea6d 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs @@ -14,7 +14,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable Indexes { get; set; } + internal List Indexes; + + public ArrayMultipleIndexFilter(List indexes) + { + Indexes = indexes; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { @@ -12,7 +17,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { @@ -16,7 +21,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable p in o) + foreach (KeyValuePair p in o) { - yield return p.Value; + yield return p.Value!; } } } diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs index 3d46708e4..20cd06880 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs @@ -11,7 +11,12 @@ namespace Newtonsoft.Json.Linq.JsonPath { internal class FieldMultipleFilter : PathFilter { - public List Names { get; set; } + internal List Names; + + public FieldMultipleFilter(List names) + { + Names = names; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { @@ -21,7 +26,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable filters, int currentPartStartIndex, bool case '(': if (_currentIndex > currentPartStartIndex) { - string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); + string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (member == "*") { member = null; @@ -136,7 +136,7 @@ private bool ParsePath(List filters, int currentPartStartIndex, bool case '.': if (_currentIndex > currentPartStartIndex) { - string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); + string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (member == "*") { member = null; @@ -177,7 +177,7 @@ private bool ParsePath(List filters, int currentPartStartIndex, bool if (_currentIndex > currentPartStartIndex) { - string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(); + string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(); if (member == "*") { member = null; @@ -196,9 +196,9 @@ private bool ParsePath(List filters, int currentPartStartIndex, bool return atPathEnd; } - private static PathFilter CreatePathFilter(string member, bool scan) + private static PathFilter CreatePathFilter(string? member, bool scan) { - PathFilter filter = (scan) ? (PathFilter)new ScanFilter {Name = member} : new FieldFilter {Name = member}; + PathFilter filter = (scan) ? (PathFilter)new ScanFilter(member) : new FieldFilter(member); return filter; } @@ -230,7 +230,7 @@ private PathFilter ParseArrayIndexer(char indexerCloseChar) { int start = _currentIndex; int? end = null; - List indexes = null; + List? indexes = null; int colonCount = 0; int? startIndex = null; int? endIndex = null; @@ -262,7 +262,7 @@ private PathFilter ParseArrayIndexer(char indexerCloseChar) int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); indexes.Add(index); - return new ArrayMultipleIndexFilter { Indexes = indexes }; + return new ArrayMultipleIndexFilter(indexes); } else if (colonCount > 0) { @@ -421,26 +421,19 @@ private PathFilter ParseQuery(char indexerCloseChar, bool scan) if (!scan) { - return new QueryFilter - { - Expression = expression - }; + return new QueryFilter(expression); } else { - return new QueryScanFilter - { - Expression = expression - }; + return new QueryScanFilter(expression); } } - private bool TryParseExpression(out List expressionPath) + private bool TryParseExpression(out List? expressionPath) { if (_expression[_currentIndex] == '$') { - expressionPath = new List(); - expressionPath.Add(RootFilter.Instance); + expressionPath = new List { RootFilter.Instance }; } else if (_expression[_currentIndex] == '@') { @@ -454,7 +447,7 @@ private bool TryParseExpression(out List expressionPath) _currentIndex++; - if (ParsePath(expressionPath, _currentIndex, true)) + if (ParsePath(expressionPath!, _currentIndex, true)) { throw new JsonException("Path ended with open query."); } @@ -471,12 +464,12 @@ private object ParseSide() { EatWhitespace(); - if (TryParseExpression(out var expressionPath)) + if (TryParseExpression(out List? expressionPath)) { EatWhitespace(); EnsureLength("Path ended with open query."); - return expressionPath; + return expressionPath!; } if (TryParseValue(out var value)) @@ -492,13 +485,13 @@ private object ParseSide() private QueryExpression ParseExpression() { - QueryExpression rootExpression = null; - CompositeExpression parentExpression = null; + QueryExpression? rootExpression = null; + CompositeExpression? parentExpression = null; while (_currentIndex < _expression.Length) { object left = ParseSide(); - object right = null; + object? right = null; QueryOperator op; if (_expression[_currentIndex] == ')' @@ -514,19 +507,14 @@ private QueryExpression ParseExpression() right = ParseSide(); } - BooleanQueryExpression booleanExpression = new BooleanQueryExpression - { - Left = left, - Operator = op, - Right = right - }; + BooleanQueryExpression booleanExpression = new BooleanQueryExpression(op, left, right); if (_expression[_currentIndex] == ')') { if (parentExpression != null) { parentExpression.Expressions.Add(booleanExpression); - return rootExpression; + return rootExpression!; } return booleanExpression; @@ -540,7 +528,7 @@ private QueryExpression ParseExpression() if (parentExpression == null || parentExpression.Operator != QueryOperator.And) { - CompositeExpression andExpression = new CompositeExpression { Operator = QueryOperator.And }; + CompositeExpression andExpression = new CompositeExpression(QueryOperator.And); parentExpression?.Expressions.Add(andExpression); @@ -563,7 +551,7 @@ private QueryExpression ParseExpression() if (parentExpression == null || parentExpression.Operator != QueryOperator.Or) { - CompositeExpression orExpression = new CompositeExpression { Operator = QueryOperator.Or }; + CompositeExpression orExpression = new CompositeExpression(QueryOperator.Or); parentExpression?.Expressions.Add(orExpression); @@ -582,7 +570,7 @@ private QueryExpression ParseExpression() throw new JsonException("Path ended with open query."); } - private bool TryParseValue(out object value) + private bool TryParseValue(out object? value) { char currentChar = _expression[_currentIndex]; if (currentChar == '\'') @@ -763,9 +751,9 @@ private string ReadRegexString() private bool Match(string s) { int currentPosition = _currentIndex; - foreach (char c in s) + for (int i = 0; i < s.Length; i++) { - if (currentPosition < _expression.Length && _expression[currentPosition] == c) + if (currentPosition < _expression.Length && _expression[currentPosition] == s[i]) { currentPosition++; } @@ -832,7 +820,7 @@ private QueryOperator ParseOperator() private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) { - List fields = null; + List? fields = null; while (_currentIndex < _expression.Length) { @@ -847,8 +835,8 @@ private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) { fields.Add(field); return (scan) - ? (PathFilter)new ScanMultipleFilter { Names = fields } - : (PathFilter)new FieldMultipleFilter { Names = fields }; + ? (PathFilter)new ScanMultipleFilter(fields) + : (PathFilter)new FieldMultipleFilter(fields); } else { diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs index 6ea77c550..abba44eed 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs @@ -8,9 +8,8 @@ internal abstract class PathFilter { public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch); - protected static JToken GetTokenIndex(JToken t, bool errorWhenNoMatch, int index) + protected static JToken? GetTokenIndex(JToken t, bool errorWhenNoMatch, int index) { - if (t is JArray a) { if (a.Count <= index) @@ -50,7 +49,7 @@ protected static JToken GetTokenIndex(JToken t, bool errorWhenNoMatch, int index } } - protected static JToken GetNextScanValue(JToken originalParent, JToken container, JToken value) + protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value) { // step into container's values if (container != null && container.HasValues) @@ -60,7 +59,7 @@ protected static JToken GetNextScanValue(JToken originalParent, JToken container else { // finished container, move to parent - while (value != null && value != originalParent && value == value.Parent.Last) + while (value != null && value != originalParent && value == value.Parent!.Last) { value = value.Parent; } diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs b/Src/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs index a65bcbfbd..69eee36cf 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs @@ -32,7 +32,12 @@ internal enum QueryOperator internal abstract class QueryExpression { - public QueryOperator Operator { get; set; } + internal QueryOperator Operator; + + public QueryExpression(QueryOperator @operator) + { + Operator = @operator; + } public abstract bool IsMatch(JToken root, JToken t); } @@ -41,7 +46,7 @@ internal class CompositeExpression : QueryExpression { public List Expressions { get; set; } - public CompositeExpression() + public CompositeExpression(QueryOperator @operator) : base(@operator) { Expressions = new List(); } @@ -76,10 +81,16 @@ public override bool IsMatch(JToken root, JToken t) internal class BooleanQueryExpression : QueryExpression { - public object Left { get; set; } - public object Right { get; set; } + public readonly object Left; + public readonly object? Right; + + public BooleanQueryExpression(QueryOperator @operator, object left, object? right) : base(@operator) + { + Left = left; + Right = right; + } - private IEnumerable GetResult(JToken root, JToken t, object o) + private IEnumerable GetResult(JToken root, JToken t, object? o) { if (o is JToken resultToken) { @@ -211,13 +222,13 @@ private static bool RegexEquals(JValue input, JValue pattern) return false; } - string regexText = (string)pattern.Value; + string regexText = (string)pattern.Value!; int patternOptionDelimiterIndex = regexText.LastIndexOf('/'); string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1); string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1); - return Regex.IsMatch((string)input.Value, patternText, MiscellaneousUtils.GetRegexOptions(optionsText)); + return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText)); } internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) @@ -240,7 +251,7 @@ internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) return false; } - string queryValueString = (string)queryValue.Value; + string queryValueString = (string)queryValue.Value!; string currentValueString; @@ -258,21 +269,21 @@ internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) else #endif { - DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); + DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value!, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); } currentValueString = writer.ToString(); } break; case JTokenType.Bytes: - currentValueString = Convert.ToBase64String((byte[])value.Value); + currentValueString = Convert.ToBase64String((byte[])value.Value!); break; case JTokenType.Guid: case JTokenType.TimeSpan: - currentValueString = value.Value.ToString(); + currentValueString = value.Value!.ToString(); break; case JTokenType.Uri: - currentValueString = ((Uri)value.Value).OriginalString; + currentValueString = ((Uri)value.Value!).OriginalString; break; default: return false; diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs index 775acd808..c528623f6 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs @@ -5,7 +5,12 @@ namespace Newtonsoft.Json.Linq.JsonPath { internal class QueryFilter : PathFilter { - public QueryExpression Expression { get; set; } + internal QueryExpression Expression; + + public QueryFilter(QueryExpression expression) + { + Expression = expression; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs index 027d02101..422376711 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs @@ -5,7 +5,12 @@ namespace Newtonsoft.Json.Linq.JsonPath { internal class QueryScanFilter : PathFilter { - public QueryExpression Expression { get; set; } + internal QueryExpression Expression; + + public QueryScanFilter(QueryExpression expression) + { + Expression = expression; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { diff --git a/Src/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs b/Src/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs index 073edd9d0..1938c1b0a 100644 --- a/Src/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs +++ b/Src/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs @@ -4,7 +4,12 @@ namespace Newtonsoft.Json.Linq.JsonPath { internal class ScanFilter : PathFilter { - public string Name { get; set; } + internal string? Name; + + public ScanFilter(string? name) + { + Name = name; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { @@ -15,11 +20,11 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable Names { get; set; } + private List _names; + + public ScanMultipleFilter(List names) + { + _names = names; + } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) { foreach (JToken c in current) { - JToken value = c; + JToken? value = c; while (true) { - JContainer container = value as JContainer; + JContainer? container = value as JContainer; value = GetNextScanValue(c, container, value); if (value == null) @@ -24,7 +29,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable net45;net40;net35;net20;netstandard1.0;netstandard1.3;netstandard2.0;portable-net45+win8+wpa81+wp8;portable-net40+win8+wpa81+wp8+sl5 $(LibraryFrameworks) - latest + 8.0 11.0.0.0 11.0.1 @@ -25,6 +25,7 @@ Newtonsoft.Json Newtonsoft.Json true + enable 2.12 true snupkg @@ -37,7 +38,9 @@ - + + + Json.NET HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants) diff --git a/Src/Newtonsoft.Json/Schema/Extensions.cs b/Src/Newtonsoft.Json/Schema/Extensions.cs index 4b9d2db7a..df8ffbaaf 100644 --- a/Src/Newtonsoft.Json/Schema/Extensions.cs +++ b/Src/Newtonsoft.Json/Schema/Extensions.cs @@ -28,6 +28,8 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchema.cs b/Src/Newtonsoft.Json/Schema/JsonSchema.cs index e7cf44198..034bd0634 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchema.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchema.cs @@ -30,6 +30,8 @@ using Newtonsoft.Json.Utilities; using System.Globalization; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs index 310ef70a1..c87ffd6f8 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs @@ -35,6 +35,8 @@ using Newtonsoft.Json.Utilities; using Newtonsoft.Json.Linq; +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs index ab41d34e7..d43939416 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs @@ -26,6 +26,8 @@ using System; using System.Collections.Generic; +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs index b1b53628f..2349589d2 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs @@ -26,6 +26,8 @@ using System; using System.Runtime.Serialization; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs index ba8245b0c..e0b3e406a 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs @@ -37,6 +37,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs index af01626d9..2c55d075a 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs @@ -28,6 +28,8 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs index 648206a7d..e29d42e8e 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs @@ -32,6 +32,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs index a01a47db0..30757f0ba 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs @@ -33,6 +33,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs index db45fac47..af5bbb7ed 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs @@ -26,6 +26,8 @@ using System; using System.Collections.ObjectModel; +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs index 4780d4b20..714aebd6f 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs @@ -32,6 +32,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs index 31ad683af..ec9181b12 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs @@ -25,6 +25,8 @@ using System; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs b/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs index c17f7a6f3..c5843bedd 100644 --- a/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs +++ b/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs @@ -35,6 +35,8 @@ #endif +#nullable disable + namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] diff --git a/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs b/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs index 0f6aa4ba6..9064700df 100644 --- a/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs +++ b/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs @@ -25,6 +25,8 @@ using System; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs b/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs index 5d69c1fb0..180053988 100644 --- a/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs +++ b/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs @@ -26,6 +26,8 @@ using System; using Newtonsoft.Json.Utilities; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs b/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs index a287e8b43..cdeaed2b3 100644 --- a/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs +++ b/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs @@ -25,6 +25,8 @@ using System; +#nullable disable + namespace Newtonsoft.Json.Schema { /// diff --git a/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs b/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs index 0645631d2..406975941 100644 --- a/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs +++ b/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs @@ -31,9 +31,9 @@ namespace Newtonsoft.Json.Serialization { internal static class CachedAttributeGetter where T : Attribute { - private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); + private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); - public static T GetAttribute(object type) + public static T? GetAttribute(object type) { return TypeAttributeCache.Get(type); } diff --git a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index 90690d47a..87a781b20 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -168,7 +168,7 @@ public class DefaultContractResolver : IContractResolver /// Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized. /// /// The naming strategy used to resolve how property names and dictionary keys are serialized. - public NamingStrategy NamingStrategy { get; set; } + public NamingStrategy? NamingStrategy { get; set; } /// /// Initializes a new instance of the class. @@ -243,7 +243,7 @@ protected virtual List GetSerializableMembers(Type objectType) if (memberSerialization != MemberSerialization.Fields) { #if HAVE_DATA_CONTRACTS - DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); + DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); #endif #pragma warning disable 618 @@ -352,9 +352,9 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute); contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization)); - Func extensionDataNameResolver = null; + Func? extensionDataNameResolver = null; - JsonObjectAttribute attribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); + JsonObjectAttribute? attribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); if (attribute != null) { contract.ItemRequired = attribute._itemRequired; @@ -363,7 +363,7 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) if (attribute.NamingStrategyType != null) { - NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute); + NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute)!; extensionDataNameResolver = s => namingStrategy.GetDictionaryKey(s); } } @@ -377,7 +377,7 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) if (contract.IsInstantiable) { - ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); + ConstructorInfo? overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); // check if a JsonConstructorAttribute has been defined and use that if (overrideConstructor != null) @@ -398,7 +398,7 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) } else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic) { - ConstructorInfo constructor = GetParameterizedConstructor(contract.NonNullableUnderlyingType); + ConstructorInfo? constructor = GetParameterizedConstructor(contract.NonNullableUnderlyingType); if (constructor != null) { contract.ParameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); @@ -409,7 +409,7 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) { // value types always have default constructor // check whether there is a constructor that matches with non-writable properties on value type - ConstructorInfo constructor = GetImmutableConstructor(contract.NonNullableUnderlyingType, contract.Properties); + ConstructorInfo? constructor = GetImmutableConstructor(contract.NonNullableUnderlyingType, contract.Properties); if (constructor != null) { contract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); @@ -471,7 +471,7 @@ private MemberInfo GetExtensionDataMemberForType(Type type) Type t = ReflectionUtils.GetMemberUnderlyingType(m); - if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type dictionaryType)) + if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type? dictionaryType)) { Type keyType = dictionaryType.GetGenericArguments()[0]; Type valueType = dictionaryType.GetGenericArguments()[1]; @@ -490,7 +490,7 @@ private MemberInfo GetExtensionDataMemberForType(Type type) private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member) { - JsonExtensionDataAttribute extensionDataAttribute = ReflectionUtils.GetAttribute(member); + JsonExtensionDataAttribute? extensionDataAttribute = ReflectionUtils.GetAttribute(member); if (extensionDataAttribute == null) { return; @@ -498,10 +498,10 @@ private static void SetExtensionDataDelegates(JsonObjectContract contract, Membe Type t = ReflectionUtils.GetMemberUnderlyingType(member); - ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type dictionaryType); + ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out Type? dictionaryType); - Type keyType = dictionaryType.GetGenericArguments()[0]; - Type valueType = dictionaryType.GetGenericArguments()[1]; + Type keyType = dictionaryType!.GetGenericArguments()[0]; + Type valueType = dictionaryType!.GetGenericArguments()[1]; Type createdType; @@ -515,27 +515,27 @@ private static void SetExtensionDataDelegates(JsonObjectContract contract, Membe createdType = t; } - Func getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(member); + Func getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(member); if (extensionDataAttribute.ReadData) { - Action setExtensionDataDictionary = (ReflectionUtils.CanSetMemberValue(member, true, false)) + Action? setExtensionDataDictionary = (ReflectionUtils.CanSetMemberValue(member, true, false)) ? JsonTypeReflector.ReflectionDelegateFactory.CreateSet(member) : null; Func createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(createdType); - MethodInfo setMethod = t.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod(); + MethodInfo? setMethod = t.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod(); if (setMethod == null) { // Item is explicitly implemented and non-public // get from dictionary interface - setMethod = dictionaryType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod(); + setMethod = dictionaryType!.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod(); } - MethodCall setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMethod); + MethodCall setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMethod!); ExtensionDataSetter extensionDataSetter = (o, key, value) => { - object dictionary = getExtensionDataDictionary(o); + object? dictionary = getExtensionDataDictionary(o); if (dictionary == null) { if (setExtensionDataDictionary == null) @@ -561,7 +561,7 @@ private static void SetExtensionDataDelegates(JsonObjectContract contract, Membe ExtensionDataGetter extensionDataGetter = o => { - object dictionary = getExtensionDataDictionary(o); + object? dictionary = getExtensionDataDictionary(o); if (dictionary == null) { return null; @@ -592,7 +592,7 @@ public IEnumerator> GetEnumerator() { foreach (KeyValuePair item in _e) { - yield return new KeyValuePair(item.Key, item.Value); + yield return new KeyValuePair(item.Key!, item.Value!); } } @@ -602,7 +602,7 @@ IEnumerator IEnumerable.GetEnumerator() } } - private ConstructorInfo GetAttributeConstructor(Type objectType) + private ConstructorInfo? GetAttributeConstructor(Type objectType) { IEnumerator en = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).GetEnumerator(); @@ -626,7 +626,7 @@ private ConstructorInfo GetAttributeConstructor(Type objectType) return null; } - private ConstructorInfo GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties) + private ConstructorInfo? GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties) { IEnumerable constructors = objectType.GetConstructors(); IEnumerator en = constructors.GetEnumerator(); @@ -640,7 +640,7 @@ private ConstructorInfo GetImmutableConstructor(Type objectType, JsonPropertyCol { foreach (ParameterInfo parameterInfo in parameters) { - JsonProperty memberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); + JsonProperty? memberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); if (memberProperty == null || memberProperty.Writable) { return null; @@ -655,7 +655,7 @@ private ConstructorInfo GetImmutableConstructor(Type objectType, JsonPropertyCol return null; } - private ConstructorInfo GetParameterizedConstructor(Type objectType) + private ConstructorInfo? GetParameterizedConstructor(Type objectType) { #if PORTABLE IEnumerable constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); @@ -692,7 +692,12 @@ protected virtual IList CreateConstructorParameters(ConstructorInf foreach (ParameterInfo parameterInfo in constructorParameters) { - JsonProperty matchingMemberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); + if (parameterInfo.Name == null) + { + continue; + } + + JsonProperty? matchingMemberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); // ensure that property will have a name from matching property or from parameterinfo // parameterinfo could have no name if generated by a proxy (I'm looking at you Castle) @@ -710,7 +715,7 @@ protected virtual IList CreateConstructorParameters(ConstructorInf return parameterCollection; } - private JsonProperty MatchProperty(JsonPropertyCollection properties, string name, Type type) + private JsonProperty? MatchProperty(JsonPropertyCollection properties, string name, Type type) { // it is possible to generate a member with a null name using Reflection.Emit // protect against an ArgumentNullException from GetClosestMatchProperty by testing for null here @@ -719,7 +724,7 @@ private JsonProperty MatchProperty(JsonPropertyCollection properties, string nam return null; } - JsonProperty property = properties.GetClosestMatchProperty(name); + JsonProperty? property = properties.GetClosestMatchProperty(name); // must match type as well as name if (property == null || property.PropertyType != type) { @@ -735,7 +740,7 @@ private JsonProperty MatchProperty(JsonPropertyCollection properties, string nam /// The matching member property. /// The constructor parameter. /// A created for the given . - protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo) + protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty? matchingMemberProperty, ParameterInfo parameterInfo) { JsonProperty property = new JsonProperty(); property.PropertyType = parameterInfo.ParameterType; @@ -774,7 +779,7 @@ protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProper /// /// Type of the object. /// The contract's default . - protected virtual JsonConverter ResolveContractConverter(Type objectType) + protected virtual JsonConverter? ResolveContractConverter(Type objectType) { return JsonTypeReflector.GetJsonConverter(objectType); } @@ -789,7 +794,7 @@ private Func GetDefaultCreator(Type createdType) #endif private void InitializeContract(JsonContract contract) { - JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); + JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); if (containerAttribute != null) { contract.IsReference = containerAttribute._isReference; @@ -797,7 +802,7 @@ private void InitializeContract(JsonContract contract) #if HAVE_DATA_CONTRACTS else { - DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); + DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); // doesn't have a null value if (dataContractAttribute != null && dataContractAttribute.IsReference) { @@ -827,11 +832,11 @@ private void ResolveCallbackMethods(JsonContract contract, Type t) { GetCallbackMethodsForType( t, - out List onSerializing, - out List onSerialized, - out List onDeserializing, - out List onDeserialized, - out List onError); + out List? onSerializing, + out List? onSerialized, + out List? onDeserializing, + out List? onDeserialized, + out List? onError); if (onSerializing != null) { @@ -859,7 +864,7 @@ private void ResolveCallbackMethods(JsonContract contract, Type t) } } - private void GetCallbackMethodsForType(Type type, out List onSerializing, out List onSerialized, out List onDeserializing, out List onDeserialized, out List onError) + private void GetCallbackMethodsForType(Type type, out List? onSerializing, out List? onSerialized, out List? onDeserializing, out List? onDeserialized, out List? onError) { onSerializing = null; onSerialized = null; @@ -870,11 +875,11 @@ private void GetCallbackMethodsForType(Type type, out List(objectType); + JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetAttribute(objectType); if (containerAttribute?.NamingStrategyType != null) { - NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute); + NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute)!; contract.DictionaryKeyResolver = s => namingStrategy.GetDictionaryKey(s); } else @@ -1017,7 +1022,7 @@ protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectTyp contract.DictionaryKeyResolver = ResolveDictionaryKey; } - ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); + ConstructorInfo? overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); if (overrideConstructor != null) { @@ -1055,7 +1060,7 @@ protected virtual JsonArrayContract CreateArrayContract(Type objectType) JsonArrayContract contract = new JsonArrayContract(objectType); InitializeContract(contract); - ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); + ConstructorInfo? overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType); if (overrideConstructor != null) { @@ -1146,10 +1151,10 @@ protected virtual JsonDynamicContract CreateDynamicContract(Type objectType) JsonDynamicContract contract = new JsonDynamicContract(objectType); InitializeContract(contract); - JsonContainerAttribute containerAttribute = JsonTypeReflector.GetAttribute(objectType); + JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetAttribute(objectType); if (containerAttribute?.NamingStrategyType != null) { - NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute); + NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(containerAttribute)!; contract.PropertyNameResolver = s => namingStrategy.GetDictionaryKey(s); } else @@ -1191,7 +1196,7 @@ protected virtual JsonContract CreateContract(Type objectType) } t = ReflectionUtils.EnsureNotNullableType(t); - JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute(t); + JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetCachedAttribute(t); if (containerAttribute is JsonObjectAttribute) { @@ -1290,7 +1295,7 @@ internal static bool CanConvertToString(Type type) return false; } - private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType) + private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo? currentCallback, ref Type? prevAttributeType) { if (!method.IsDefined(attributeType, false)) { @@ -1374,7 +1379,7 @@ protected virtual IList CreateProperties(Type type, MemberSerializ // nametable is not thread-safe for multiple writers lock (nameTable) { - property.PropertyName = nameTable.Add(property.PropertyName); + property.PropertyName = nameTable.Add(property.PropertyName!); } properties.AddProperty(property); @@ -1462,11 +1467,11 @@ protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerializa private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess) { #if HAVE_DATA_CONTRACTS - DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); + DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); - MemberInfo memberInfo = attributeProvider as MemberInfo; + MemberInfo? memberInfo = attributeProvider as MemberInfo; - DataMemberAttribute dataMemberAttribute; + DataMemberAttribute? dataMemberAttribute; if (dataContractAttribute != null && memberInfo != null) { dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo)memberInfo); @@ -1477,8 +1482,8 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att } #endif - JsonPropertyAttribute propertyAttribute = JsonTypeReflector.GetAttribute(attributeProvider); - JsonRequiredAttribute requiredAttribute = JsonTypeReflector.GetAttribute(attributeProvider); + JsonPropertyAttribute? propertyAttribute = JsonTypeReflector.GetAttribute(attributeProvider); + JsonRequiredAttribute? requiredAttribute = JsonTypeReflector.GetAttribute(attributeProvider); string mappedName; bool hasSpecifiedName; @@ -1500,9 +1505,9 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att hasSpecifiedName = false; } - JsonContainerAttribute containerAttribute = JsonTypeReflector.GetAttribute(declaringType); + JsonContainerAttribute? containerAttribute = JsonTypeReflector.GetAttribute(declaringType); - NamingStrategy namingStrategy; + NamingStrategy? namingStrategy; if (propertyAttribute?.NamingStrategyType != null) { namingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(propertyAttribute.NamingStrategyType, propertyAttribute.NamingStrategyParameters); @@ -1605,7 +1610,7 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att // the class type might have a converter but the property converter takes precedence property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider); - DefaultValueAttribute defaultValueAttribute = JsonTypeReflector.GetAttribute(attributeProvider); + DefaultValueAttribute? defaultValueAttribute = JsonTypeReflector.GetAttribute(attributeProvider); if (defaultValueAttribute != null) { property.DefaultValue = defaultValueAttribute.Value; @@ -1628,7 +1633,7 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att } } - private Predicate CreateShouldSerializeTest(MemberInfo member) + private Predicate? CreateShouldSerializeTest(MemberInfo member) { MethodInfo shouldSerializeMethod = member.DeclaringType.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes); @@ -1637,15 +1642,15 @@ private Predicate CreateShouldSerializeTest(MemberInfo member) return null; } - MethodCall shouldSerializeCall = + MethodCall shouldSerializeCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(shouldSerializeMethod); - return o => (bool)shouldSerializeCall(o); + return o => (bool)shouldSerializeCall(o)!; } private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) { - MemberInfo specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + MemberInfo? specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (specifiedMember == null) { specifiedMember = member.DeclaringType.GetField(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); @@ -1656,7 +1661,7 @@ private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, boo return; } - Func specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(specifiedMember); + Func specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(specifiedMember)!; property.GetIsSpecified = o => (bool)specifiedPropertyGet(o); diff --git a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs index 90af80338..1adf55a62 100644 --- a/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs +++ b/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs @@ -43,19 +43,19 @@ public class DefaultSerializationBinder : { internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder(); - private readonly ThreadSafeStore, Type> _typeCache; + private readonly ThreadSafeStore, Type> _typeCache; /// /// Initializes a new instance of the class. /// public DefaultSerializationBinder() { - _typeCache = new ThreadSafeStore, Type>(GetTypeFromTypeNameKey); + _typeCache = new ThreadSafeStore, Type>(GetTypeFromTypeNameKey); } - private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) + private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) { - string assemblyName = typeNameKey.Value1; + string? assemblyName = typeNameKey.Value1; string typeName = typeNameKey.Value2; if (assemblyName != null) @@ -96,7 +96,7 @@ private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, assemblyName)); } - Type type = assembly.GetType(typeName); + Type? type = assembly.GetType(typeName); if (type == null) { // if generic type, try manually parsing the type arguments for the case of dynamically loaded assemblies @@ -127,9 +127,9 @@ private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) } } - private Type GetGenericTypeFromTypeName(string typeName, Assembly assembly) + private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly) { - Type type = null; + Type? type = null; int openBracketIndex = typeName.IndexOf('['); if (openBracketIndex >= 0) { @@ -159,7 +159,7 @@ private Type GetGenericTypeFromTypeName(string typeName, Assembly assembly) { string typeArgAssemblyQualifiedName = typeName.Substring(typeArgStartIndex, i - typeArgStartIndex); - StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(typeArgAssemblyQualifiedName); + StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(typeArgAssemblyQualifiedName); genericTypeArguments.Add(GetTypeByName(typeNameKey)); } break; @@ -173,7 +173,7 @@ private Type GetGenericTypeFromTypeName(string typeName, Assembly assembly) return type; } - private Type GetTypeByName(StructMultiKey typeNameKey) + private Type GetTypeByName(StructMultiKey typeNameKey) { return _typeCache.Get(typeNameKey); } @@ -186,9 +186,9 @@ private Type GetTypeByName(StructMultiKey typeNameKey) /// /// The type of the object the formatter creates a new instance of. /// - public override Type BindToType(string assemblyName, string typeName) + public override Type BindToType(string? assemblyName, string typeName) { - return GetTypeByName(new StructMultiKey(assemblyName, typeName)); + return GetTypeByName(new StructMultiKey(assemblyName, typeName)); } /// @@ -201,7 +201,7 @@ public override Type BindToType(string assemblyName, string typeName) #if HAVE_SERIALIZATION_BINDER_BIND_TO_NAME override #endif - void BindToName(Type serializedType, out string assemblyName, out string typeName) + void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { #if !HAVE_FULL_REFLECTION assemblyName = serializedType.GetTypeInfo().Assembly.FullName; diff --git a/Src/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs b/Src/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs index 0f8b8fbf5..23ece092c 100644 --- a/Src/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs @@ -43,7 +43,7 @@ private TraceEventType GetTraceEventType(TraceLevel level) /// The at which to write this trace. /// The trace message. /// The trace exception. This parameter is optional. - public void Trace(TraceLevel level, string message, Exception ex) + public void Trace(TraceLevel level, string message, Exception? ex) { if (level == TraceLevel.Off) { diff --git a/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs b/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs index ec9231c7b..cb19a61e0 100644 --- a/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs +++ b/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs @@ -42,8 +42,8 @@ namespace Newtonsoft.Json.Serialization public class DynamicValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; - private Func _getter; - private Action _setter; + private Func? _getter; + private Action? _setter; /// /// Initializes a new instance of the class. @@ -60,7 +60,7 @@ public DynamicValueProvider(MemberInfo memberInfo) /// /// The target to set the value on. /// The value to set on the target. - public void SetValue(object target, object value) + public void SetValue(object target, object? value) { try { @@ -98,7 +98,7 @@ public void SetValue(object target, object value) /// /// The target to get the value from. /// The value. - public object GetValue(object target) + public object? GetValue(object target) { try { diff --git a/Src/Newtonsoft.Json/Serialization/ErrorContext.cs b/Src/Newtonsoft.Json/Serialization/ErrorContext.cs index 366064a0c..173fb7f75 100644 --- a/Src/Newtonsoft.Json/Serialization/ErrorContext.cs +++ b/Src/Newtonsoft.Json/Serialization/ErrorContext.cs @@ -32,7 +32,7 @@ namespace Newtonsoft.Json.Serialization /// public class ErrorContext { - internal ErrorContext(object originalObject, object member, string path, Exception error) + internal ErrorContext(object? originalObject, object? member, string path, Exception error) { OriginalObject = originalObject; Member = member; @@ -52,13 +52,13 @@ internal ErrorContext(object originalObject, object member, string path, Excepti /// Gets the original object that caused the error. /// /// The original object that caused the error. - public object OriginalObject { get; } + public object? OriginalObject { get; } /// /// Gets the member that caused the error. /// /// The member that caused the error. - public object Member { get; } + public object? Member { get; } /// /// Gets the path of the JSON location where the error occurred. diff --git a/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs b/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs index 1b16c6072..8231abbb4 100644 --- a/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs +++ b/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs @@ -36,7 +36,7 @@ public class ErrorEventArgs : EventArgs /// Gets the current object the error event is being raised against. /// /// The current object the error event is being raised against. - public object CurrentObject { get; } + public object? CurrentObject { get; } /// /// Gets the error context. @@ -49,7 +49,7 @@ public class ErrorEventArgs : EventArgs /// /// The current object. /// The error context. - public ErrorEventArgs(object currentObject, ErrorContext errorContext) + public ErrorEventArgs(object? currentObject, ErrorContext errorContext) { CurrentObject = currentObject; ErrorContext = errorContext; diff --git a/Src/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs b/Src/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs index ae2a3086f..99da718de 100644 --- a/Src/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs +++ b/Src/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs @@ -43,8 +43,8 @@ namespace Newtonsoft.Json.Serialization public class ExpressionValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; - private Func _getter; - private Action _setter; + private Func? _getter; + private Action? _setter; /// /// Initializes a new instance of the class. @@ -61,7 +61,7 @@ public ExpressionValueProvider(MemberInfo memberInfo) /// /// The target to set the value on. /// The value to set on the target. - public void SetValue(object target, object value) + public void SetValue(object target, object? value) { try { @@ -99,7 +99,7 @@ public void SetValue(object target, object value) /// /// The target to get the value from. /// The value. - public object GetValue(object target) + public object? GetValue(object target) { try { diff --git a/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs b/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs index bf70891b7..64ce1c3fc 100644 --- a/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs +++ b/Src/Newtonsoft.Json/Serialization/ISerializationBinder.cs @@ -40,7 +40,7 @@ public interface ISerializationBinder /// Specifies the name of the serialized object. /// Specifies the name of the serialized object /// The type of the object the formatter creates a new instance of. - Type BindToType(string assemblyName, string typeName); + Type BindToType(string? assemblyName, string typeName); /// /// When implemented, controls the binding of a serialized object to a type. @@ -48,6 +48,6 @@ public interface ISerializationBinder /// The type of the object the formatter creates a new instance of. /// Specifies the name of the serialized object. /// Specifies the name of the serialized object. - void BindToName(Type serializedType, out string assemblyName, out string typeName); + void BindToName(Type serializedType, out string? assemblyName, out string? typeName); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/ITraceWriter.cs b/Src/Newtonsoft.Json/Serialization/ITraceWriter.cs index ac0b166ed..57f24721c 100644 --- a/Src/Newtonsoft.Json/Serialization/ITraceWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/ITraceWriter.cs @@ -23,6 +23,6 @@ public interface ITraceWriter /// The at which to write this trace. /// The trace message. /// The trace exception. This parameter is optional. - void Trace(TraceLevel level, string message, Exception ex); + void Trace(TraceLevel level, string message, Exception? ex); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/IValueProvider.cs b/Src/Newtonsoft.Json/Serialization/IValueProvider.cs index 921724f81..7bfd610a6 100644 --- a/Src/Newtonsoft.Json/Serialization/IValueProvider.cs +++ b/Src/Newtonsoft.Json/Serialization/IValueProvider.cs @@ -35,13 +35,13 @@ public interface IValueProvider /// /// The target to set the value on. /// The value to set on the target. - void SetValue(object target, object value); + void SetValue(object target, object? value); /// /// Gets the value. /// /// The target to get the value from. /// The value. - object GetValue(object target); + object? GetValue(object target); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs index d7f4106f4..d09446849 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs @@ -31,6 +31,7 @@ using System.Reflection; using Newtonsoft.Json.Utilities; using System.Collections; +using System.Diagnostics; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -49,7 +50,7 @@ public class JsonArrayContract : JsonContainerContract /// Gets the of the collection items. /// /// The of the collection items. - public Type CollectionItemType { get; } + public Type? CollectionItemType { get; } /// /// Gets a value indicating whether the collection type is a multidimensional array. @@ -57,26 +58,26 @@ public class JsonArrayContract : JsonContainerContract /// true if the collection type is a multidimensional array; otherwise, false. public bool IsMultidimensionalArray { get; } - private readonly Type _genericCollectionDefinitionType; + private readonly Type? _genericCollectionDefinitionType; - private Type _genericWrapperType; - private ObjectConstructor _genericWrapperCreator; - private Func _genericTemporaryCollectionCreator; + private Type? _genericWrapperType; + private ObjectConstructor? _genericWrapperCreator; + private Func? _genericTemporaryCollectionCreator; internal bool IsArray { get; } internal bool ShouldCreateWrapper { get; } internal bool CanDeserialize { get; private set; } - private readonly ConstructorInfo _parameterizedConstructor; + private readonly ConstructorInfo? _parameterizedConstructor; - private ObjectConstructor _parameterizedCreator; - private ObjectConstructor _overrideCreator; + private ObjectConstructor? _parameterizedCreator; + private ObjectConstructor? _overrideCreator; - internal ObjectConstructor ParameterizedCreator + internal ObjectConstructor? ParameterizedCreator { get { - if (_parameterizedCreator == null) + if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } @@ -89,7 +90,7 @@ internal ObjectConstructor ParameterizedCreator /// Gets or sets the function used to create the object. When set this function will override . /// /// The function used to create the object. - public ObjectConstructor OverrideCreator + public ObjectConstructor? OverrideCreator { get => _overrideCreator; set @@ -120,7 +121,7 @@ public JsonArrayContract(Type underlyingType) bool canDeserialize; - Type tempCollectionType; + Type? tempCollectionType; if (IsArray) { CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType); @@ -251,11 +252,12 @@ public JsonArrayContract(Type underlyingType) } #endif - if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract( + if (CollectionItemType != null && + ImmutableCollectionsUtils.TryBuildImmutableForArrayContract( NonNullableUnderlyingType, CollectionItemType, - out Type immutableCreatedType, - out ObjectConstructor immutableParameterizedCreator)) + out Type? immutableCreatedType, + out ObjectConstructor? immutableParameterizedCreator)) { CreatedType = immutableCreatedType; _parameterizedCreator = immutableParameterizedCreator; @@ -268,6 +270,8 @@ internal IWrappedCollection CreateWrapper(object list) { if (_genericWrapperCreator == null) { + Debug.Assert(_genericCollectionDefinitionType != null); + _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType); Type constructorArgument; @@ -311,7 +315,7 @@ private void StoreFSharpListCreatorIfNecessary(Type underlyingType) if (!HasParameterizedCreatorInternal && underlyingType.Name == FSharpUtils.FSharpListTypeName) { FSharpUtils.EnsureInitialized(underlyingType.Assembly()); - _parameterizedCreator = FSharpUtils.CreateSeq(CollectionItemType); + _parameterizedCreator = FSharpUtils.CreateSeq(CollectionItemType!); } } #endif diff --git a/Src/Newtonsoft.Json/Serialization/JsonContainerContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContainerContract.cs index f1e7796b8..9956ed312 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContainerContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContainerContract.cs @@ -42,11 +42,11 @@ namespace Newtonsoft.Json.Serialization /// public class JsonContainerContract : JsonContract { - private JsonContract _itemContract; - private JsonContract _finalItemContract; + private JsonContract? _itemContract; + private JsonContract? _finalItemContract; // will be null for containers that don't have an item type (e.g. IList) or for complex objects - internal JsonContract ItemContract + internal JsonContract? ItemContract { get => _itemContract; set @@ -64,13 +64,13 @@ internal JsonContract ItemContract } // the final (i.e. can't be inherited from like a sealed class or valuetype) item contract - internal JsonContract FinalItemContract => _finalItemContract; + internal JsonContract? FinalItemContract => _finalItemContract; /// /// Gets or sets the default collection items . /// /// The converter. - public JsonConverter ItemConverter { get; set; } + public JsonConverter? ItemConverter { get; set; } /// /// Gets or sets a value indicating whether the collection items preserve object references. @@ -97,7 +97,7 @@ internal JsonContract ItemContract internal JsonContainerContract(Type underlyingType) : base(underlyingType) { - JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetCachedAttribute(underlyingType); + JsonContainerAttribute? jsonContainerAttribute = JsonTypeReflector.GetCachedAttribute(underlyingType); if (jsonContainerAttribute != null) { diff --git a/Src/Newtonsoft.Json/Serialization/JsonContract.cs b/Src/Newtonsoft.Json/Serialization/JsonContract.cs index 37365bb6d..c77470291 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonContract.cs @@ -67,13 +67,13 @@ internal enum JsonContractType /// The object to set extension data on. /// The extension data key. /// The extension data value. - public delegate void ExtensionDataSetter(object o, string key, object value); + public delegate void ExtensionDataSetter(object o, string key, object? value); /// /// Gets extension data for an object during serialization. /// /// The object to set extension data on. - public delegate IEnumerable> ExtensionDataGetter(object o); + public delegate IEnumerable>? ExtensionDataGetter(object o); /// /// Contract details for a used by the . @@ -90,11 +90,11 @@ public abstract class JsonContract internal bool IsSealed; internal bool IsInstantiable; - private List _onDeserializedCallbacks; - private IList _onDeserializingCallbacks; - private IList _onSerializedCallbacks; - private IList _onSerializingCallbacks; - private IList _onErrorCallbacks; + private List? _onDeserializedCallbacks; + private List? _onDeserializingCallbacks; + private List? _onSerializedCallbacks; + private List? _onSerializingCallbacks; + private List? _onErrorCallbacks; private Type _createdType; /// @@ -112,6 +112,7 @@ public Type CreatedType get => _createdType; set { + ValidationUtils.ArgumentNotNull(value, nameof(value)); _createdType = value; IsSealed = _createdType.IsSealed(); @@ -129,14 +130,14 @@ public Type CreatedType /// Gets or sets the default for this contract. /// /// The converter. - public JsonConverter Converter { get; set; } + public JsonConverter? Converter { get; set; } /// /// Gets the internally resolved for the contract's type. /// This converter is used as a fallback converter when no other converter is resolved. /// Setting will always override this converter. /// - public JsonConverter InternalConverter { get; internal set; } + public JsonConverter? InternalConverter { get; internal set; } /// /// Gets or sets all methods called immediately after deserialization of the object. @@ -227,7 +228,7 @@ public IList OnErrorCallbacks /// Gets or sets the default creator method used to create the object. /// /// The default creator method used to create the object. - public Func DefaultCreator { get; set; } + public Func? DefaultCreator { get; set; } /// /// Gets or sets a value indicating whether the default creator is non-public. @@ -249,7 +250,7 @@ internal JsonContract(Type underlyingType) NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType; - CreatedType = NonNullableUnderlyingType; + _createdType = CreatedType = NonNullableUnderlyingType; IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType); IsEnum = NonNullableUnderlyingType.IsEnum(); diff --git a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs index c486be2bd..5d93af9ae 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs @@ -45,41 +45,41 @@ public class JsonDictionaryContract : JsonContainerContract /// Gets or sets the dictionary key resolver. /// /// The dictionary key resolver. - public Func DictionaryKeyResolver { get; set; } + public Func? DictionaryKeyResolver { get; set; } /// /// Gets the of the dictionary keys. /// /// The of the dictionary keys. - public Type DictionaryKeyType { get; } + public Type? DictionaryKeyType { get; } /// /// Gets the of the dictionary values. /// /// The of the dictionary values. - public Type DictionaryValueType { get; } + public Type? DictionaryValueType { get; } - internal JsonContract KeyContract { get; set; } + internal JsonContract? KeyContract { get; set; } - private readonly Type _genericCollectionDefinitionType; + private readonly Type? _genericCollectionDefinitionType; - private Type _genericWrapperType; - private ObjectConstructor _genericWrapperCreator; + private Type? _genericWrapperType; + private ObjectConstructor? _genericWrapperCreator; - private Func _genericTemporaryDictionaryCreator; + private Func? _genericTemporaryDictionaryCreator; internal bool ShouldCreateWrapper { get; } - private readonly ConstructorInfo _parameterizedConstructor; + private readonly ConstructorInfo? _parameterizedConstructor; - private ObjectConstructor _overrideCreator; - private ObjectConstructor _parameterizedCreator; + private ObjectConstructor? _overrideCreator; + private ObjectConstructor? _parameterizedCreator; - internal ObjectConstructor ParameterizedCreator + internal ObjectConstructor? ParameterizedCreator { get { - if (_parameterizedCreator == null) + if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } @@ -92,7 +92,7 @@ internal ObjectConstructor ParameterizedCreator /// Gets or sets the function used to create the object. When set this function will override . /// /// The function used to create the object. - public ObjectConstructor OverrideCreator + public ObjectConstructor? OverrideCreator { get => _overrideCreator; set => _overrideCreator = value; @@ -115,8 +115,8 @@ public JsonDictionaryContract(Type underlyingType) { ContractType = JsonContractType.Dictionary; - Type keyType; - Type valueType; + Type? keyType; + Type? valueType; if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType)) { @@ -204,12 +204,14 @@ public JsonDictionaryContract(Type underlyingType) } #endif - if (ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract( - underlyingType, - DictionaryKeyType, - DictionaryValueType, - out Type immutableCreatedType, - out ObjectConstructor immutableParameterizedCreator)) + if (DictionaryKeyType != null && + DictionaryValueType != null && + ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract( + underlyingType, + DictionaryKeyType, + DictionaryValueType, + out Type? immutableCreatedType, + out ObjectConstructor? immutableParameterizedCreator)) { CreatedType = immutableCreatedType; _parameterizedCreator = immutableParameterizedCreator; @@ -223,7 +225,7 @@ internal IWrappedDictionary CreateWrapper(object dictionary) { _genericWrapperType = typeof(DictionaryWrapper<,>).MakeGenericType(DictionaryKeyType, DictionaryValueType); - ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType }); + ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType! }); _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(genericWrapperConstructor); } diff --git a/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs b/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs index f8a6ad391..5908890ba 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs @@ -46,13 +46,13 @@ public class JsonDynamicContract : JsonContainerContract /// Gets or sets the property name resolver. /// /// The property name resolver. - public Func PropertyNameResolver { get; set; } + public Func? PropertyNameResolver { get; set; } private readonly ThreadSafeStore>> _callSiteGetters = new ThreadSafeStore>>(CreateCallSiteGetter); - private readonly ThreadSafeStore>> _callSiteSetters = - new ThreadSafeStore>>(CreateCallSiteSetter); + private readonly ThreadSafeStore>> _callSiteSetters = + new ThreadSafeStore>>(CreateCallSiteSetter); private static CallSite> CreateCallSiteGetter(string name) { @@ -61,11 +61,11 @@ private static CallSite> CreateCallSiteGetter(str return CallSite>.Create(new NoThrowGetBinderMember(getMemberBinder)); } - private static CallSite> CreateCallSiteSetter(string name) + private static CallSite> CreateCallSiteSetter(string name) { SetMemberBinder binder = (SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils)); - return CallSite>.Create(new NoThrowSetBinderMember(binder)); + return CallSite>.Create(new NoThrowSetBinderMember(binder)); } /// @@ -80,7 +80,7 @@ public JsonDynamicContract(Type underlyingType) Properties = new JsonPropertyCollection(UnderlyingType); } - internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object value) + internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, nameof(dynamicProvider)); @@ -100,11 +100,11 @@ internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string na } } - internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object value) + internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, nameof(dynamicProvider)); - CallSite> callSite = _callSiteSetters.Get(name); + CallSite> callSite = _callSiteSetters.Get(name); object result = callSite.Target(callSite, dynamicProvider, value); diff --git a/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs b/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs index 52f61ae23..46992bc67 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs @@ -36,9 +36,9 @@ internal class JsonFormatterConverter : IFormatterConverter { private readonly JsonSerializerInternalReader _reader; private readonly JsonISerializableContract _contract; - private readonly JsonProperty _member; + private readonly JsonProperty? _member; - public JsonFormatterConverter(JsonSerializerInternalReader reader, JsonISerializableContract contract, JsonProperty member) + public JsonFormatterConverter(JsonSerializerInternalReader reader, JsonISerializableContract contract, JsonProperty? member) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(contract, nameof(contract)); @@ -56,7 +56,7 @@ private T GetTokenValue(object value) return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture); } - public object Convert(object value, Type type) + public object? Convert(object value, Type type) { ValidationUtils.ArgumentNotNull(value, nameof(value)); @@ -72,12 +72,9 @@ public object Convert(object value, TypeCode typeCode) { ValidationUtils.ArgumentNotNull(value, nameof(value)); - if (value is JValue v) - { - value = v.Value; - } + object? resolvedValue = (value is JValue v) ? v.Value : value; - return System.Convert.ChangeType(value, typeCode, CultureInfo.InvariantCulture); + return System.Convert.ChangeType(resolvedValue, typeCode, CultureInfo.InvariantCulture); } public bool ToBoolean(object value) diff --git a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs index f78181f45..55ea9e3a7 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs @@ -38,7 +38,7 @@ public class JsonISerializableContract : JsonContainerContract /// Gets or sets the object constructor. /// /// The object constructor. - public ObjectConstructor ISerializableCreator { get; set; } + public ObjectConstructor? ISerializableCreator { get; set; } /// /// Initializes a new instance of the class. diff --git a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs index 0a839a85d..221843dbd 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs @@ -91,13 +91,13 @@ public JsonPropertyCollection CreatorParameters /// This function is called with a collection of arguments which are defined by the collection. /// /// The function used to create the object. - public ObjectConstructor OverrideCreator + public ObjectConstructor? OverrideCreator { get => _overrideCreator; set => _overrideCreator = value; } - internal ObjectConstructor ParameterizedCreator + internal ObjectConstructor? ParameterizedCreator { get => _parameterizedCreator; set => _parameterizedCreator = value; @@ -106,17 +106,17 @@ internal ObjectConstructor ParameterizedCreator /// /// Gets or sets the extension data setter. /// - public ExtensionDataSetter ExtensionDataSetter { get; set; } + public ExtensionDataSetter? ExtensionDataSetter { get; set; } /// /// Gets or sets the extension data getter. /// - public ExtensionDataGetter ExtensionDataGetter { get; set; } + public ExtensionDataGetter? ExtensionDataGetter { get; set; } /// /// Gets or sets the extension data value type. /// - public Type ExtensionDataValueType + public Type? ExtensionDataValueType { get => _extensionDataValueType; set @@ -130,14 +130,14 @@ public Type ExtensionDataValueType /// Gets or sets the extension data name resolver. /// /// The extension data name resolver. - public Func ExtensionDataNameResolver { get; set; } + public Func? ExtensionDataNameResolver { get; set; } internal bool ExtensionDataIsJToken; private bool? _hasRequiredOrDefaultValueProperties; - private ObjectConstructor _overrideCreator; - private ObjectConstructor _parameterizedCreator; - private JsonPropertyCollection _creatorParameters; - private Type _extensionDataValueType; + private ObjectConstructor? _overrideCreator; + private ObjectConstructor? _parameterizedCreator; + private JsonPropertyCollection? _creatorParameters; + private Type? _extensionDataValueType; internal bool HasRequiredOrDefaultValueProperties { diff --git a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs index 38fe85169..1979c5995 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonProperty.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonProperty.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Diagnostics; using System.Reflection; using Newtonsoft.Json.Utilities; @@ -41,20 +42,20 @@ public class JsonProperty internal Required? _required; internal bool _hasExplicitDefaultValue; - private object _defaultValue; + private object? _defaultValue; private bool _hasGeneratedDefaultValue; - private string _propertyName; + private string? _propertyName; internal bool _skipPropertyNameEscape; - private Type _propertyType; + private Type? _propertyType; // use to cache contract during deserialization - internal JsonContract PropertyContract { get; set; } + internal JsonContract? PropertyContract { get; set; } /// /// Gets or sets the name of the property. /// /// The name of the property. - public string PropertyName + public string? PropertyName { get => _propertyName; set @@ -68,7 +69,7 @@ public string PropertyName /// Gets or sets the type that declared this property. /// /// The type that declared this property. - public Type DeclaringType { get; set; } + public Type? DeclaringType { get; set; } /// /// Gets or sets the order of serialization of a member. @@ -80,25 +81,25 @@ public string PropertyName /// Gets or sets the name of the underlying member or parameter. /// /// The name of the underlying member or parameter. - public string UnderlyingName { get; set; } + public string? UnderlyingName { get; set; } /// /// Gets the that will get and set the during serialization. /// /// The that will get and set the during serialization. - public IValueProvider ValueProvider { get; set; } + public IValueProvider? ValueProvider { get; set; } /// /// Gets or sets the for this property. /// /// The for this property. - public IAttributeProvider AttributeProvider { get; set; } + public IAttributeProvider? AttributeProvider { get; set; } /// /// Gets or sets the type of the property. /// /// The type of the property. - public Type PropertyType + public Type? PropertyType { get => _propertyType; set @@ -116,14 +117,14 @@ public Type PropertyType /// If set this converter takes precedence over the contract converter for the property type. /// /// The converter. - public JsonConverter Converter { get; set; } + public JsonConverter? Converter { get; set; } /// /// Gets or sets the member converter. /// /// The member converter. [Obsolete("MemberConverter is obsolete. Use Converter instead.")] - public JsonConverter MemberConverter + public JsonConverter? MemberConverter { get => Converter; set => Converter = value; @@ -157,7 +158,7 @@ public JsonConverter MemberConverter /// Gets the default value. /// /// The default value. - public object DefaultValue + public object? DefaultValue { get { @@ -175,7 +176,7 @@ public object DefaultValue } } - internal object GetResolvedDefaultValue() + internal object? GetResolvedDefaultValue() { if (_propertyType == null) { @@ -184,7 +185,7 @@ internal object GetResolvedDefaultValue() if (!_hasExplicitDefaultValue && !_hasGeneratedDefaultValue) { - _defaultValue = ReflectionUtils.GetDefaultValue(PropertyType); + _defaultValue = ReflectionUtils.GetDefaultValue(_propertyType); _hasGeneratedDefaultValue = true; } @@ -248,25 +249,25 @@ public Required Required /// Gets or sets a predicate used to determine whether the property should be serialized. /// /// A predicate used to determine whether the property should be serialized. - public Predicate ShouldSerialize { get; set; } + public Predicate? ShouldSerialize { get; set; } /// /// Gets or sets a predicate used to determine whether the property should be deserialized. /// /// A predicate used to determine whether the property should be deserialized. - public Predicate ShouldDeserialize { get; set; } + public Predicate? ShouldDeserialize { get; set; } /// /// Gets or sets a predicate used to determine whether the property should be serialized. /// /// A predicate used to determine whether the property should be serialized. - public Predicate GetIsSpecified { get; set; } + public Predicate? GetIsSpecified { get; set; } /// /// Gets or sets an action used to set whether the property has been deserialized. /// /// An action used to set whether the property has been deserialized. - public Action SetIsSpecified { get; set; } + public Action? SetIsSpecified { get; set; } /// /// Returns a that represents this instance. @@ -276,14 +277,14 @@ public Required Required /// public override string ToString() { - return PropertyName; + return PropertyName ?? string.Empty; } /// /// Gets or sets the converter used when serializing the property's collection items. /// /// The collection's items converter. - public JsonConverter ItemConverter { get; set; } + public JsonConverter? ItemConverter { get; set; } /// /// Gets or sets whether this property's collection items are serialized as a reference. @@ -305,13 +306,16 @@ public override string ToString() internal void WritePropertyName(JsonWriter writer) { + string? propertyName = PropertyName; + Debug.Assert(propertyName != null); + if (_skipPropertyNameEscape) { - writer.WritePropertyName(PropertyName, false); + writer.WritePropertyName(propertyName, false); } else { - writer.WritePropertyName(PropertyName); + writer.WritePropertyName(propertyName); } } } diff --git a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs index 9bb5a5cf2..d631a83f1 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs @@ -29,6 +29,9 @@ using System.Collections.ObjectModel; using Newtonsoft.Json.Utilities; using System.Globalization; +using System.Runtime.CompilerServices; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Newtonsoft.Json.Serialization { @@ -61,7 +64,7 @@ public JsonPropertyCollection(Type type) /// The key for the specified element. protected override string GetKeyForItem(JsonProperty item) { - return item.PropertyName; + return item.PropertyName!; } /// @@ -70,6 +73,8 @@ protected override string GetKeyForItem(JsonProperty item) /// The property to add to the collection. public void AddProperty(JsonProperty property) { + Debug.Assert(property.PropertyName != null); + if (Contains(property.PropertyName)) { // don't overwrite existing property with ignored property @@ -129,9 +134,9 @@ public void AddProperty(JsonProperty property) /// /// Name of the property. /// A matching property if found. - public JsonProperty GetClosestMatchProperty(string propertyName) + public JsonProperty? GetClosestMatchProperty(string propertyName) { - JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal); + JsonProperty? property = GetProperty(propertyName, StringComparison.Ordinal); if (property == null) { property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); @@ -140,7 +145,7 @@ public JsonProperty GetClosestMatchProperty(string propertyName) return property; } - private bool TryGetValue(string key, out JsonProperty item) + private bool TryGetValue(string key, [NotNullWhen(true)]out JsonProperty? item) { if (Dictionary == null) { @@ -157,12 +162,12 @@ private bool TryGetValue(string key, out JsonProperty item) /// The name of the property to get. /// Type property name string comparison. /// A matching property if found. - public JsonProperty GetProperty(string propertyName, StringComparison comparisonType) + public JsonProperty? GetProperty(string propertyName, StringComparison comparisonType) { // KeyedCollection has an ordinal comparer if (comparisonType == StringComparison.Ordinal) { - if (TryGetValue(propertyName, out JsonProperty property)) + if (TryGetValue(propertyName, out JsonProperty? property)) { return property; } diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs index 73d8670bd..8e76dc0f7 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs @@ -47,12 +47,12 @@ int IEqualityComparer.GetHashCode(object obj) } } - private ErrorContext _currentErrorContext; - private BidirectionalDictionary _mappings; + private ErrorContext? _currentErrorContext; + private BidirectionalDictionary? _mappings; internal readonly JsonSerializer Serializer; - internal readonly ITraceWriter TraceWriter; - protected JsonSerializerProxy InternalSerializer; + internal readonly ITraceWriter? TraceWriter; + protected JsonSerializerProxy? InternalSerializer; protected JsonSerializerInternalBase(JsonSerializer serializer) { @@ -81,7 +81,7 @@ internal BidirectionalDictionary DefaultReferenceMappings } } - protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract containerContract, JsonProperty property) + protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract? containerContract, JsonProperty property) { NullValueHandling resolvedNullValueHandling = property.NullValueHandling @@ -91,7 +91,7 @@ protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract contain return resolvedNullValueHandling; } - private ErrorContext GetErrorContext(object currentObject, object member, string path, Exception error) + private ErrorContext GetErrorContext(object? currentObject, object? member, string path, Exception error) { if (_currentErrorContext == null) { @@ -116,7 +116,7 @@ protected void ClearErrorContext() _currentErrorContext = null; } - protected bool IsErrorHandled(object currentObject, JsonContract contract, object keyValue, IJsonLineInfo lineInfo, string path, Exception ex) + protected bool IsErrorHandled(object? currentObject, JsonContract? contract, object? keyValue, IJsonLineInfo? lineInfo, string path, Exception ex) { ErrorContext errorContext = GetErrorContext(currentObject, keyValue, path, ex); diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index d0ee4d526..7b6c9ed3c 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -40,11 +40,12 @@ using System.Runtime.Serialization; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; - #endif namespace Newtonsoft.Json.Serialization @@ -93,10 +94,10 @@ public void Populate(JsonReader reader, object target) { reader.ReadAndAssert(); - string id = null; + string? id = null; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName - && string.Equals(reader.Value.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) + && string.Equals(reader.Value!.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal)) { reader.ReadAndAssert(); id = reader.Value?.ToString(); @@ -123,28 +124,33 @@ public void Populate(JsonReader reader, object target) } } - private JsonContract GetContractSafe(Type type) + private JsonContract? GetContractSafe(Type? type) { if (type == null) { return null; } + return GetContract(type); + } + + private JsonContract GetContract(Type type) + { return Serializer._contractResolver.ResolveContract(type); } - public object Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent) + public object? Deserialize(JsonReader reader, Type? objectType, bool checkAdditionalContent) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } - JsonContract contract = GetContractSafe(objectType); + JsonContract? contract = GetContractSafe(objectType); try { - JsonConverter converter = GetConverter(contract, null, null, null); + JsonConverter? converter = GetConverter(contract, null, null, null); if (reader.TokenType == JsonToken.None && !reader.ReadForType(contract, converter != null)) { @@ -156,11 +162,11 @@ public object Deserialize(JsonReader reader, Type objectType, bool checkAddition return null; } - object deserializedValue; + object? deserializedValue; if (converter != null && converter.CanRead) { - deserializedValue = DeserializeConvertable(converter, reader, objectType, null); + deserializedValue = DeserializeConvertable(converter, reader, objectType!, null); } else { @@ -208,7 +214,7 @@ private JsonSerializerProxy GetInternalSerializer() return InternalSerializer; } - private JToken CreateJToken(JsonReader reader, JsonContract contract) + private JToken? CreateJToken(JsonReader reader, JsonContract? contract) { ValidationUtils.ArgumentNotNull(reader, nameof(reader)); @@ -225,7 +231,7 @@ private JToken CreateJToken(JsonReader reader, JsonContract contract) } } - JToken token; + JToken? token; using (JTokenWriter writer = new JTokenWriter()) { writer.WriteToken(reader); @@ -248,7 +254,7 @@ private JToken CreateJObject(JsonReader reader) { if (reader.TokenType == JsonToken.PropertyName) { - string propertyName = (string)reader.Value; + string propertyName = (string)reader.Value!; if (!reader.ReadAndMoveToContent()) { break; @@ -269,7 +275,7 @@ private JToken CreateJObject(JsonReader reader) else { writer.WriteEndObject(); - return writer.Token; + return writer.Token!; } } while (reader.Read()); @@ -277,7 +283,7 @@ private JToken CreateJObject(JsonReader reader) } } - private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) + private object? CreateValueInternal(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { if (contract != null && contract.ContractType == JsonContractType.Linq) { @@ -301,7 +307,7 @@ private object CreateValueInternal(JsonReader reader, Type objectType, JsonContr case JsonToken.Bytes: return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.String: - string s = (string)reader.Value; + string s = (string)reader.Value!; // string that needs to be returned as a byte array should be base 64 decoded if (objectType == typeof(byte[])) @@ -317,7 +323,7 @@ private object CreateValueInternal(JsonReader reader, Type objectType, JsonContr return EnsureType(reader, s, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.StartConstructor: - string constructorName = reader.Value.ToString(); + string constructorName = reader.Value!.ToString(); return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Null: @@ -331,7 +337,7 @@ private object CreateValueInternal(JsonReader reader, Type objectType, JsonContr return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Raw: - return new JRaw((string)reader.Value); + return new JRaw((string?)reader.Value); case JsonToken.Comment: // ignore break; @@ -343,7 +349,7 @@ private object CreateValueInternal(JsonReader reader, Type objectType, JsonContr throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } - private static bool CoerceEmptyStringToNull(Type objectType, JsonContract contract, string s) + private static bool CoerceEmptyStringToNull(Type? objectType, JsonContract? contract, string s) { return string.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable; } @@ -372,9 +378,9 @@ internal string GetExpectedDescription(JsonContract contract) } } - private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty) + private JsonConverter? GetConverter(JsonContract? contract, JsonConverter? memberConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty) { - JsonConverter converter = null; + JsonConverter? converter = null; if (memberConverter != null) { // member attribute converter @@ -390,13 +396,12 @@ private JsonConverter GetConverter(JsonContract contract, JsonConverter memberCo } else if (contract != null) { - JsonConverter matchingConverter; if (contract.Converter != null) { // class attribute converter converter = contract.Converter; } - else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null) + else if (Serializer.GetMatchingConverter(contract.UnderlyingType) is JsonConverter matchingConverter) { // passed in converters converter = matchingConverter; @@ -410,10 +415,10 @@ private JsonConverter GetConverter(JsonContract contract, JsonConverter memberCo return converter; } - private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue) + private object? CreateObject(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { - string id; - Type resolvedObjectType = objectType; + string? id; + Type? resolvedObjectType = objectType; if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore) { @@ -440,7 +445,7 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con reader = tokenReader; } - if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out id)) + if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out object? newValue, out id)) { return newValue; } @@ -448,7 +453,7 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con else { reader.ReadAndAssert(); - if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out id)) + if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out object? newValue, out id)) { return newValue; } @@ -459,6 +464,9 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con return CreateJObject(reader); } + Debug.Assert(resolvedObjectType != null); + Debug.Assert(contract != null); + switch (contract.ContractType) { case JsonContractType.Object: @@ -490,7 +498,7 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con // if the content is inside $value then read past it if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName - && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal)) + && string.Equals(reader.Value!.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal)) { reader.ReadAndAssert(); @@ -501,7 +509,7 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType); } - object value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue); + object? value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue); reader.ReadAndAssert(); return value; @@ -544,7 +552,7 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con if (createdFromNonDefaultCreator) { - ObjectConstructor creator = dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator; + ObjectConstructor creator = (dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator)!; return creator(dictionary); } @@ -553,8 +561,8 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con return wrappedDictionary.UnderlyingDictionary; } - targetDictionary = dictionary; - } + targetDictionary = dictionary; + } else { targetDictionary = PopulateDictionary(dictionaryContract.ShouldCreateWrapper || !(existingValue is IDictionary) ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary)existingValue, reader, dictionaryContract, member, id); @@ -581,38 +589,29 @@ private object CreateObject(JsonReader reader, Type objectType, JsonContract con throw JsonSerializationException.Create(reader, message); } - private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id) + private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, [NotNullWhen(true)]out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.StartObject) { - JObject current = (JObject)reader.CurrentToken; + JObject current = (JObject)reader.CurrentToken!; - JToken refToken = current[JsonTypeReflector.RefPropertyName]; - if (refToken != null) + JProperty? refProperty = current.Property(JsonTypeReflector.RefPropertyName, StringComparison.Ordinal); + if (refProperty != null) { + JToken refToken = refProperty.Value; if (refToken.Type != JTokenType.String && refToken.Type != JTokenType.Null) { throw JsonSerializationException.Create(refToken, refToken.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null); } - JToken property = refToken.Parent; - JToken additionalContent = null; - if (property.Next != null) - { - additionalContent = property.Next; - } - else if (property.Previous != null) - { - additionalContent = property.Previous; - } - - string reference = (string)refToken; + string? reference = (string?)refProperty; if (reference != null) { + JToken? additionalContent = refProperty.Next ?? refProperty.Previous; if (additionalContent != null) { throw JsonSerializationException.Create(additionalContent, additionalContent.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null); @@ -629,15 +628,15 @@ private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectTyp return true; } } - JToken typeToken = current[JsonTypeReflector.TypePropertyName]; + JToken? typeToken = current[JsonTypeReflector.TypePropertyName]; if (typeToken != null) { - string qualifiedTypeName = (string)typeToken; + string? qualifiedTypeName = (string?)typeToken; JsonReader typeTokenReader = typeToken.CreateReader(); typeTokenReader.ReadAndAssert(); - ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); + ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName!); - JToken valueToken = current[JsonTypeReflector.ValuePropertyName]; + JToken? valueToken = current[JsonTypeReflector.ValuePropertyName]; if (valueToken != null) { while (true) @@ -645,7 +644,7 @@ private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectTyp reader.ReadAndAssert(); if (reader.TokenType == JsonToken.PropertyName) { - if ((string)reader.Value == JsonTypeReflector.ValuePropertyName) + if ((string)reader.Value! == JsonTypeReflector.ValuePropertyName) { return false; } @@ -656,12 +655,12 @@ private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectTyp } } } - JToken idToken = current[JsonTypeReflector.IdPropertyName]; + JToken? idToken = current[JsonTypeReflector.IdPropertyName]; if (idToken != null) { - id = (string)idToken; + id = (string?)idToken; } - JToken valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName]; + JToken? valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName]; if (valuesToken != null) { JsonReader listReader = valuesToken.CreateReader(); @@ -677,14 +676,14 @@ private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectTyp return false; } - private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id) + private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (propertyName.Length > 0 && propertyName[0] == '$') { @@ -694,7 +693,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref do { - propertyName = reader.Value.ToString(); + propertyName = reader.Value!.ToString(); if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal)) { @@ -704,7 +703,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName)); } - string reference = reader.Value?.ToString(); + string? reference = reader.Value?.ToString(); reader.ReadAndAssert(); @@ -719,7 +718,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { - TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null); + TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue!.GetType())), null); } return true; @@ -732,7 +731,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal)) { reader.ReadAndAssert(); - string qualifiedTypeName = reader.Value.ToString(); + string qualifiedTypeName = reader.Value!.ToString(); ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); @@ -752,7 +751,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal)) { reader.ReadAndAssert(); - object list = CreateList(reader, objectType, contract, member, existingValue, id); + object? list = CreateList(reader, objectType, contract, member, existingValue, id); reader.ReadAndAssert(); newValue = list; return true; @@ -767,7 +766,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref return false; } - private void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, string qualifiedTypeName) + private void ResolveTypeName(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, string qualifiedTypeName) { TypeNameHandling resolvedTypeNameHandling = member?.TypeNameHandling @@ -777,7 +776,7 @@ private void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonCon if (resolvedTypeNameHandling != TypeNameHandling.None) { - StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName); + StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName); Type specifiedType; try @@ -809,7 +808,7 @@ private void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonCon } objectType = specifiedType; - contract = GetContractSafe(specifiedType); + contract = GetContract(specifiedType); } } @@ -832,15 +831,18 @@ private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType return arrayContract; } - private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id) + private object? CreateList(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, object? existingValue, string? id) { - object value; + object? value; if (HasNoDefinedType(contract)) { return CreateJToken(reader, contract); } + Debug.Assert(objectType != null); + Debug.Assert(contract != null); + JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract); if (existingValue == null) @@ -883,7 +885,7 @@ private object CreateList(JsonReader reader, Type objectType, JsonContract contr { if (arrayContract.IsMultidimensionalArray) { - list = CollectionUtils.ToMultidimensionalArray(list, arrayContract.CollectionItemType, contract.CreatedType.GetArrayRank()); + list = CollectionUtils.ToMultidimensionalArray(list, arrayContract.CollectionItemType!, contract.CreatedType.GetArrayRank()); } else if (arrayContract.IsArray) { @@ -893,7 +895,7 @@ private object CreateList(JsonReader reader, Type objectType, JsonContract contr } else { - ObjectConstructor creator = arrayContract.OverrideCreator ?? arrayContract.ParameterizedCreator; + ObjectConstructor creator = (arrayContract.OverrideCreator ?? arrayContract.ParameterizedCreator)!; return creator(list); } @@ -918,7 +920,7 @@ private object CreateList(JsonReader reader, Type objectType, JsonContract contr return value; } - private bool HasNoDefinedType(JsonContract contract) + private bool HasNoDefinedType(JsonContract? contract) { return (contract == null || contract.UnderlyingType == typeof(object) || contract.ContractType == JsonContractType.Linq #if HAVE_DYNAMIC @@ -927,14 +929,15 @@ private bool HasNoDefinedType(JsonContract contract) ); } - private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType) + private object? EnsureType(JsonReader reader, object? value, CultureInfo culture, JsonContract? contract, Type? targetType) { if (targetType == null) { return value; } - Type valueType = ReflectionUtils.GetObjectType(value); + Debug.Assert(contract != null); + Type? valueType = ReflectionUtils.GetObjectType(value); // type of value and type of target don't match // attempt to convert value's type to target's type @@ -993,7 +996,7 @@ private object EnsureType(JsonReader reader, object value, CultureInfo culture, return value; } - private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target) + private bool SetPropertyValue(JsonProperty property, JsonConverter? propertyConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty, JsonReader reader, object target) { bool skipSettingProperty = CalculatePropertyDetails( property, @@ -1003,8 +1006,8 @@ private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConve reader, target, out bool useExistingValue, - out object currentValue, - out JsonContract propertyContract, + out object? currentValue, + out JsonContract? propertyContract, out bool gottenCurrentValue, out bool ignoredValue); @@ -1020,16 +1023,16 @@ private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConve return false; } - object value; + object? value; if (propertyConverter != null && propertyConverter.CanRead) { - if (!gottenCurrentValue && target != null && property.Readable) + if (!gottenCurrentValue && property.Readable) { - currentValue = property.ValueProvider.GetValue(target); + currentValue = property.ValueProvider!.GetValue(target); } - value = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue); + value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, currentValue); } else { @@ -1042,7 +1045,7 @@ private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConve if ((!useExistingValue || value != currentValue) && ShouldSetPropertyValue(property, containerContract as JsonObjectContract, value)) { - property.ValueProvider.SetValue(target, value); + property.ValueProvider!.SetValue(target, value); if (property.SetIsSpecified != null) { @@ -1063,14 +1066,14 @@ private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConve private bool CalculatePropertyDetails( JsonProperty property, - ref JsonConverter propertyConverter, - JsonContainerContract containerContract, - JsonProperty containerProperty, + ref JsonConverter? propertyConverter, + JsonContainerContract? containerContract, + JsonProperty? containerProperty, JsonReader reader, object target, out bool useExistingValue, - out object currentValue, - out JsonContract propertyContract, + out object? currentValue, + out JsonContract? propertyContract, out bool gottenCurrentValue, out bool ignoredValue) { @@ -1099,12 +1102,12 @@ private bool CalculatePropertyDetails( && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject || propertyConverter != null) && property.Readable) { - currentValue = property.ValueProvider.GetValue(target); + currentValue = property.ValueProvider!.GetValue(target); gottenCurrentValue = true; if (currentValue != null) { - propertyContract = GetContractSafe(currentValue.GetType()); + propertyContract = GetContract(currentValue.GetType()); useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType()); } @@ -1143,7 +1146,7 @@ private bool CalculatePropertyDetails( } else { - propertyContract = GetContractSafe(currentValue.GetType()); + propertyContract = GetContract(currentValue.GetType()); if (propertyContract != property.PropertyContract) { @@ -1176,7 +1179,7 @@ private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) return ((value & flag) == flag); } - private bool ShouldSetPropertyValue(JsonProperty property, JsonObjectContract contract, object value) + private bool ShouldSetPropertyValue(JsonProperty property, JsonObjectContract? contract, object? value) { if (value == null && ResolvedNullValueHandling(contract, property) == NullValueHandling.Ignore) { @@ -1334,7 +1337,7 @@ private void OnDeserialized(JsonReader reader, JsonContract contract, object val contract.InvokeOnDeserialized(value, Serializer._context); } - private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, string id) + private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty? containerProperty, string? id) { object underlyingDictionary = dictionary is IWrappedDictionary wrappedDictionary ? wrappedDictionary.UnderlyingDictionary : dictionary; @@ -1357,7 +1360,7 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso contract.ItemContract = GetContractSafe(contract.DictionaryValueType); } - JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); + JsonConverter? dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); PrimitiveTypeCode keyTypeCode = (contract.KeyContract is JsonPrimitiveContract keyContract) ? keyContract.TypeCode : PrimitiveTypeCode.Empty; bool finished = false; @@ -1366,7 +1369,7 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso switch (reader.TokenType) { case JsonToken.PropertyName: - object keyValue = reader.Value; + object keyValue = reader.Value!; if (CheckPropertyName(reader, keyValue.ToString())) { continue; @@ -1384,7 +1387,7 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso { keyValue = DateTimeUtils.TryParseDateTime(keyValue.ToString(), reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out DateTime dt) ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType); + : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; break; } #if HAVE_DATE_TIME_OFFSET @@ -1393,12 +1396,12 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso { keyValue = DateTimeUtils.TryParseDateTimeOffset(keyValue.ToString(), reader.DateFormatString, reader.Culture, out DateTimeOffset dt) ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType); + : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; break; } #endif default: - keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType); + keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; break; } } @@ -1412,10 +1415,10 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } - object itemValue; + object? itemValue; if (dictionaryValueConverter != null && dictionaryValueConverter.CanRead) { - itemValue = DeserializeConvertable(dictionaryValueConverter, reader, contract.DictionaryValueType, null); + itemValue = DeserializeConvertable(dictionaryValueConverter, reader, contract.DictionaryValueType!, null); } else { @@ -1455,7 +1458,7 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso return underlyingDictionary; } - private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id) + private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { int rank = contract.UnderlyingType.GetArrayRank(); @@ -1466,8 +1469,8 @@ private object PopulateMultidimensionalArray(IList list, JsonReader reader, Json OnDeserializing(reader, contract, list); - JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType); - JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); + JsonContract? collectionItemContract = GetContractSafe(contract.CollectionItemType); + JsonConverter? collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); int? previousErrorIndex = null; Stack listStack = new Stack(); @@ -1495,11 +1498,11 @@ private object PopulateMultidimensionalArray(IList list, JsonReader reader, Json case JsonToken.Comment: break; default: - object value; + object? value; if (collectionItemConverter != null && collectionItemConverter.CanRead) { - value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null); + value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType!, null); } else { @@ -1586,7 +1589,7 @@ private object PopulateMultidimensionalArray(IList list, JsonReader reader, Json return list; } - private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object currentObject, string message) + private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object? currentObject, string message) { try { @@ -1605,8 +1608,9 @@ private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contrac } } - private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id) + private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { +#pragma warning disable CS8600, CS8602, CS8603, CS8604 object underlyingList = list is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : list; if (id != null) @@ -1630,7 +1634,7 @@ private object PopulateList(IList list, JsonReader reader, JsonArrayContract con contract.ItemContract = GetContractSafe(contract.CollectionItemType); } - JsonConverter collectionItemConverter = GetConverter(contract.ItemContract, null, contract, containerProperty); + JsonConverter? collectionItemConverter = GetConverter(contract.ItemContract, null, contract, containerProperty); int? previousErrorIndex = null; @@ -1649,7 +1653,7 @@ private object PopulateList(IList list, JsonReader reader, JsonArrayContract con case JsonToken.Comment: break; default: - object value; + object? value; if (collectionItemConverter != null && collectionItemConverter.CanRead) { @@ -1702,10 +1706,11 @@ private object PopulateList(IList list, JsonReader reader, JsonArrayContract con OnDeserialized(reader, contract, underlyingList); return underlyingList; +#pragma warning restore CS8600, CS8602, CS8603, CS8604 } #if HAVE_BINARY_SERIALIZATION - private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, string id) + private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty? member, string? id) { Type objectType = contract.UnderlyingType; @@ -1731,7 +1736,7 @@ private object CreateISerializable(JsonReader reader, JsonISerializableContract switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value.ToString(); + string memberName = reader.Value!.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); @@ -1777,15 +1782,15 @@ private object CreateISerializable(JsonReader reader, JsonISerializableContract return createdObject; } - internal object CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty member) + internal object? CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty? member) { - JsonContract itemContract = GetContractSafe(type); - JsonConverter itemConverter = GetConverter(itemContract, null, contract, member); + JsonContract? itemContract = GetContractSafe(type); + JsonConverter? itemConverter = GetConverter(itemContract, null, contract, member); JsonReader tokenReader = token.CreateReader(); tokenReader.ReadAndAssert(); // Move to first token - object result; + object? result; if (itemConverter != null && itemConverter.CanRead) { result = DeserializeConvertable(itemConverter, tokenReader, type, null); @@ -1800,7 +1805,7 @@ internal object CreateISerializableItem(JToken token, Type type, JsonISerializab #endif #if HAVE_DYNAMIC - private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, string id) + private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty? member, string? id) { IDynamicMetaObjectProvider newObject; @@ -1834,7 +1839,7 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value.ToString(); + string memberName = reader.Value!.ToString(); try { @@ -1844,7 +1849,7 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js } // first attempt to find a settable property, otherwise fall back to a dynamic set without type - JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName); + JsonProperty? property = contract.Properties.GetClosestMatchProperty(memberName); if (property != null && property.Writable && !property.Ignored) { @@ -1853,7 +1858,7 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js property.PropertyContract = GetContractSafe(property.PropertyType); } - JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.Converter, null, null); + JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, null, null); if (!SetPropertyValue(property, propertyConverter, null, member, reader, newObject)) { @@ -1862,15 +1867,15 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js } else { - Type t = (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType : typeof(IDynamicMetaObjectProvider); + Type t = (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType! : typeof(IDynamicMetaObjectProvider); - JsonContract dynamicMemberContract = GetContractSafe(t); - JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member); + JsonContract? dynamicMemberContract = GetContractSafe(t); + JsonConverter? dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member); - object value; + object? value; if (dynamicMemberConverter != null && dynamicMemberConverter.CanRead) { - value = DeserializeConvertable(dynamicMemberConverter, reader, t, null); + value = DeserializeConvertable(dynamicMemberConverter!, reader, t, null); } else { @@ -1913,15 +1918,20 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js internal class CreatorPropertyContext { - public string Name; - public JsonProperty Property; - public JsonProperty ConstructorProperty; + public readonly string Name; + public JsonProperty? Property; + public JsonProperty? ConstructorProperty; public PropertyPresence? Presence; - public object Value; + public object? Value; public bool Used; + + public CreatorPropertyContext(string name) + { + Name = name; + } } - private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor creator, string id) + private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty? containerProperty, ObjectConstructor creator, string? id) { ValidationUtils.ArgumentNotNull(creator, nameof(creator)); @@ -1949,10 +1959,9 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj { if (propertyContexts.All(p => p.Property != property)) { - propertyContexts.Add(new CreatorPropertyContext + propertyContexts.Add(new CreatorPropertyContext(property.PropertyName!) { Property = property, - Name = property.PropertyName, Presence = PropertyPresence.None }); } @@ -1960,7 +1969,7 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj } } - object[] creatorParameterValues = new object[contract.CreatorParameters.Count]; + object?[] creatorParameterValues = new object?[contract.CreatorParameters.Count]; foreach (CreatorPropertyContext context in propertyContexts) { @@ -1969,7 +1978,7 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj { if (context.Property != null && context.Presence == null) { - object v = context.Value; + object? v = context.Value; PropertyPresence propertyPresence; if (v == null) { @@ -1990,10 +1999,10 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj } } - JsonProperty constructorProperty = context.ConstructorProperty; + JsonProperty? constructorProperty = context.ConstructorProperty; if (constructorProperty == null && context.Property != null) { - constructorProperty = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName, context.Property.UnderlyingName); + constructorProperty = contract.CreatorParameters.ForgivingCaseSensitiveFind(p => p.PropertyName!, context.Property.UnderlyingName!); } if (constructorProperty != null && !constructorProperty.Ignored) @@ -2015,7 +2024,7 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj reader, constructorProperty.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, - constructorProperty.PropertyContract, + constructorProperty.PropertyContract!, constructorProperty.PropertyType); } } @@ -2049,17 +2058,17 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj } JsonProperty property = context.Property; - object value = context.Value; + object? value = context.Value; if (ShouldSetPropertyValue(property, contract, value)) { - property.ValueProvider.SetValue(createdObject, value); + property.ValueProvider!.SetValue(createdObject, value); context.Used = true; } else if (!property.Writable && value != null) { // handle readonly collection/dictionary properties - JsonContract propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType); + JsonContract propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType!); if (propertyContract.ContractType == JsonContractType.Array) { @@ -2067,7 +2076,7 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj if (propertyArrayContract.CanDeserialize && !propertyArrayContract.IsReadOnlyOrFixedSize) { - object createdObjectCollection = property.ValueProvider.GetValue(createdObject); + object? createdObjectCollection = property.ValueProvider!.GetValue(createdObject); if (createdObjectCollection != null) { IList createdObjectCollectionWrapper = (propertyArrayContract.ShouldCreateWrapper) ? propertyArrayContract.CreateWrapper(createdObjectCollection) : (IList)createdObjectCollection; @@ -2086,7 +2095,7 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj if (!dictionaryContract.IsReadOnlyOrFixedSize) { - object createdObjectDictionary = property.ValueProvider.GetValue(createdObject); + object? createdObjectDictionary = property.ValueProvider!.GetValue(createdObject); if (createdObjectDictionary != null) { IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary; @@ -2149,14 +2158,14 @@ private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObj return createdObject; } - private object DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue) + private object? DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object? existingValue) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null); } - object value = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer()); + object? value = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer()); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { @@ -2166,7 +2175,7 @@ private object DeserializeConvertable(JsonConverter converter, JsonReader reader return value; } - private List ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType) + private List ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty? containerProperty, JsonReader reader, Type objectType) { List propertyValues = new List(); bool exit = false; @@ -2175,17 +2184,16 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value.ToString(); + string memberName = reader.Value!.ToString(); - CreatorPropertyContext creatorPropertyContext = new CreatorPropertyContext + CreatorPropertyContext creatorPropertyContext = new CreatorPropertyContext(memberName) { - Name = memberName, ConstructorProperty = contract.CreatorParameters.GetClosestMatchProperty(memberName), Property = contract.Properties.GetClosestMatchProperty(memberName) }; propertyValues.Add(creatorPropertyContext); - JsonProperty property = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; + JsonProperty? property = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; if (property != null && !property.Ignored) { if (property.PropertyContract == null) @@ -2193,7 +2201,7 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC property.PropertyContract = GetContractSafe(property.PropertyType); } - JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, containerProperty); + JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, containerProperty); if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) { @@ -2202,7 +2210,7 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC if (propertyConverter != null && propertyConverter.CanRead) { - creatorPropertyContext.Value = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null); + creatorPropertyContext.Value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, null); } else { @@ -2256,9 +2264,9 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC return propertyValues; } - public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultCreator) + public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty? containerMember, JsonProperty? containerProperty, string? id, out bool createdFromNonDefaultCreator) { - object newObject = null; + object? newObject = null; if (objectContract.OverrideCreator != null) { @@ -2299,12 +2307,12 @@ public object CreateNewObject(JsonReader reader, JsonObjectContract objectContra return newObject; } - private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id) + private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty? member, string? id) { OnDeserializing(reader, contract, newObject); // only need to keep a track of properties' presence if they are required or a value should be defaulted if missing - Dictionary propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) + Dictionary? propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None) : null; @@ -2322,7 +2330,7 @@ private object PopulateObject(object newObject, JsonReader reader, JsonObjectCon { case JsonToken.PropertyName: { - string propertyName = reader.Value.ToString(); + string propertyName = reader.Value!.ToString(); if (CheckPropertyName(reader, propertyName)) { @@ -2333,7 +2341,7 @@ private object PopulateObject(object newObject, JsonReader reader, JsonObjectCon { // attempt exact case match first // then try match ignoring case - JsonProperty property = contract.Properties.GetClosestMatchProperty(propertyName); + JsonProperty? property = contract.Properties.GetClosestMatchProperty(propertyName); if (property == null) { @@ -2373,7 +2381,7 @@ private object PopulateObject(object newObject, JsonReader reader, JsonObjectCon property.PropertyContract = GetContractSafe(property.PropertyType); } - JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, member); + JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, member); if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) { @@ -2467,13 +2475,13 @@ private bool CheckPropertyName(JsonReader reader, string memberName) return false; } - private void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o) + private void SetExtensionData(JsonObjectContract contract, JsonProperty? member, JsonReader reader, string memberName, object o) { if (contract.ExtensionDataSetter != null) { try { - object value = ReadExtensionDataValue(contract, member, reader); + object? value = ReadExtensionDataValue(contract, member, reader); contract.ExtensionDataSetter(o, memberName, value); } @@ -2488,9 +2496,9 @@ private void SetExtensionData(JsonObjectContract contract, JsonProperty member, } } - private object ReadExtensionDataValue(JsonObjectContract contract, JsonProperty member, JsonReader reader) + private object? ReadExtensionDataValue(JsonObjectContract contract, JsonProperty? member, JsonReader reader) { - object value; + object? value; if (contract.ExtensionDataIsJToken) { value = JToken.ReadFrom(reader); @@ -2527,7 +2535,7 @@ private void EndProcessProperty(object newObject, JsonReader reader, JsonObjectC 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)); + property.ValueProvider!.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract!, property.PropertyType)); } } break; @@ -2557,7 +2565,7 @@ private void EndProcessProperty(object newObject, JsonReader reader, JsonObjectC } } - private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary requiredProperties) + private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary? requiredProperties) { if (property != null && requiredProperties != null) { @@ -2565,7 +2573,7 @@ private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dicti switch (reader.TokenType) { case JsonToken.String: - propertyPresence = (CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value)) + propertyPresence = (CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value!)) ? PropertyPresence.Null : PropertyPresence.Value; break; diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 9ce79c69d..fc0ded0b4 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -37,18 +37,19 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; using System.Runtime.Serialization; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; - #endif namespace Newtonsoft.Json.Serialization { internal class JsonSerializerInternalWriter : JsonSerializerInternalBase { - private Type _rootType; + private Type? _rootType; private int _rootLevel; private readonly List _serializeStack = new List(); @@ -57,7 +58,7 @@ public JsonSerializerInternalWriter(JsonSerializer serializer) { } - public void Serialize(JsonWriter jsonWriter, object value, Type objectType) + public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { if (jsonWriter == null) { @@ -67,13 +68,13 @@ public void Serialize(JsonWriter jsonWriter, object value, Type objectType) _rootType = objectType; _rootLevel = _serializeStack.Count + 1; - JsonContract contract = GetContractSafe(value); + JsonContract? contract = GetContractSafe(value); try { if (ShouldWriteReference(value, null, contract, null, null)) { - WriteReference(jsonWriter, value); + WriteReference(jsonWriter, value!); } else { @@ -113,17 +114,22 @@ private JsonSerializerProxy GetInternalSerializer() return InternalSerializer; } - private JsonContract GetContractSafe(object value) + private JsonContract? GetContractSafe(object? value) { if (value == null) { return null; } + return GetContract(value); + } + + private JsonContract GetContract(object value) + { return Serializer._contractResolver.ResolveContract(value.GetType()); } - private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) + private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (contract.TypeCode == PrimitiveTypeCode.Bytes) { @@ -145,7 +151,7 @@ private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveCo JsonWriter.WriteValue(writer, contract.TypeCode, value); } - private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) + private void SerializeValue(JsonWriter writer, object? value, JsonContract? valueContract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (value == null) { @@ -153,7 +159,9 @@ private void SerializeValue(JsonWriter writer, object value, JsonContract valueC return; } - JsonConverter converter = + Debug.Assert(valueContract != null); + + JsonConverter? converter = member?.Converter ?? containerProperty?.ItemConverter ?? containerContract?.ItemConverter ?? @@ -209,7 +217,7 @@ private void SerializeValue(JsonWriter writer, object value, JsonContract valueC } } - private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty) + private bool? ResolveIsReference(JsonContract contract, JsonProperty? property, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { bool? isReference = null; @@ -237,12 +245,15 @@ private void SerializeValue(JsonWriter writer, object value, JsonContract valueC return isReference; } - private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty) + private bool ShouldWriteReference(object? value, JsonProperty? property, JsonContract? valueContract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (value == null) { return false; } + + Debug.Assert(valueContract != null); + if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String) { return false; @@ -270,7 +281,7 @@ private bool ShouldWriteReference(object value, JsonProperty property, JsonContr return Serializer.GetReferenceResolver().IsReferenced(this, value); } - private bool ShouldWriteProperty(object memberValue, JsonObjectContract containerContract, JsonProperty property) + private bool ShouldWriteProperty(object? memberValue, JsonObjectContract? containerContract, JsonProperty property) { if (memberValue == null && ResolvedNullValueHandling(containerContract, property) == NullValueHandling.Ignore) { @@ -286,9 +297,16 @@ private bool ShouldWriteProperty(object memberValue, JsonObjectContract containe return true; } - private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty) + private bool CheckForCircularReference(JsonWriter writer, object? value, JsonProperty? property, JsonContract? contract, JsonContainerContract? containerContract, JsonProperty? containerProperty) { - if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) + if (value == null) + { + return true; + } + + Debug.Assert(contract != null); + + if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return true; } @@ -376,7 +394,7 @@ private string GetReference(JsonWriter writer, object value) } } - internal static bool TryConvertToString(object value, Type type, out string s) + internal static bool TryConvertToString(object value, Type type, [NotNullWhen(true)]out string? s) { #if HAVE_TYPE_DESCRIPTOR if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter converter)) @@ -394,10 +412,9 @@ internal static bool TryConvertToString(object value, Type type, out string s) } #endif - type = value as Type; - if (type != null) + if (value is Type t) { - s = type.AssemblyQualifiedName; + s = t.AssemblyQualifiedName; return true; } @@ -409,7 +426,7 @@ private void SerializeString(JsonWriter writer, object value, JsonStringContract { OnSerializing(writer, contract, value); - TryConvertToString(value, contract.UnderlyingType, out string s); + TryConvertToString(value, contract.UnderlyingType, out string? s); writer.WriteValue(s); OnSerialized(writer, contract, value); @@ -435,7 +452,7 @@ private void OnSerialized(JsonWriter writer, JsonContract contract, object value contract.InvokeOnSerialized(value, Serializer._context); } - private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); @@ -450,7 +467,7 @@ private void SerializeObject(JsonWriter writer, object value, JsonObjectContract JsonProperty property = contract.Properties[index]; try { - if (!CalculatePropertyValues(writer, value, contract, member, property, out JsonContract memberContract, out object memberValue)) + if (!CalculatePropertyValues(writer, value, contract, member, property, out JsonContract? memberContract, out object? memberValue)) { continue; } @@ -471,13 +488,13 @@ private void SerializeObject(JsonWriter writer, object value, JsonObjectContract } } - IEnumerable> extensionData = contract.ExtensionDataGetter?.Invoke(value); + IEnumerable>? extensionData = contract.ExtensionDataGetter?.Invoke(value); if (extensionData != null) { foreach (KeyValuePair e in extensionData) { - JsonContract keyContract = GetContractSafe(e.Key); - JsonContract valueContract = GetContractSafe(e.Value); + JsonContract keyContract = GetContract(e.Key); + JsonContract? valueContract = GetContractSafe(e.Value); string propertyName = GetPropertyName(writer, e.Key, keyContract, out _); @@ -488,7 +505,7 @@ private void SerializeObject(JsonWriter writer, object value, JsonObjectContract if (ShouldWriteReference(e.Value, null, valueContract, contract, member)) { writer.WritePropertyName(propertyName); - WriteReference(writer, e.Value); + WriteReference(writer, e.Value!); } else { @@ -511,35 +528,35 @@ private void SerializeObject(JsonWriter writer, object value, JsonObjectContract OnSerialized(writer, contract, value); } - private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue) + private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, JsonProperty property, [NotNullWhen(true)]out JsonContract? memberContract, [NotNullWhen(true)]out object? memberValue) { if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) { if (property.PropertyContract == null) { - property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType); + property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType!); } - memberValue = property.ValueProvider.GetValue(value); + memberValue = property.ValueProvider!.GetValue(value); memberContract = (property.PropertyContract.IsSealed) ? property.PropertyContract : GetContractSafe(memberValue); if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) { - if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) + if (ShouldWriteReference(memberValue, property, memberContract!, contract, member)) { property.WritePropertyName(writer); - WriteReference(writer, memberValue); + WriteReference(writer, memberValue!); return false; } - if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) + if (!CheckForCircularReference(writer, memberValue, property, memberContract!, contract, member)) { return false; } if (memberValue == null) { - JsonObjectContract objectContract = contract as JsonObjectContract; + JsonObjectContract? objectContract = contract as JsonObjectContract; Required resolvedRequired = property._required ?? objectContract?.ItemRequired ?? Required.Default; if (resolvedRequired == Required.Always) { @@ -560,7 +577,7 @@ private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContai return false; } - private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { writer.WriteStartObject(); @@ -576,14 +593,14 @@ private void WriteObjectStart(JsonWriter writer, object value, JsonContract cont } } - private bool HasCreatorParameter(JsonContainerContract contract, JsonProperty property) + private bool HasCreatorParameter(JsonContainerContract? contract, JsonProperty property) { if (!(contract is JsonObjectContract objectContract)) { return false; } - return objectContract.CreatorParameters.Contains(property.PropertyName); + return objectContract.CreatorParameters.Contains(property.PropertyName!); } private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value) @@ -627,7 +644,7 @@ private bool HasFlag(TypeNameHandling value, TypeNameHandling flag) return ((value & flag) == flag); } - private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) { @@ -658,7 +675,7 @@ private void SerializeConvertable(JsonWriter writer, JsonConverter converter, ob } } - private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { object underlyingList = values is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : values; @@ -678,7 +695,7 @@ private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContr { try { - JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); + JsonContract? valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { @@ -721,7 +738,7 @@ private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContr OnSerialized(writer, contract, underlyingList); } - private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, values); @@ -741,7 +758,7 @@ private void SerializeMultidimensionalArray(JsonWriter writer, Array values, Jso OnSerialized(writer, contract, values); } - private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices) + private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, int initialDepth, int[] indices) { int dimension = indices.Length; int[] newIndices = new int[dimension + 1]; @@ -763,7 +780,7 @@ private void SerializeMultidimensionalArray(JsonWriter writer, Array values, Jso try { - JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); + JsonContract? valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { @@ -798,7 +815,7 @@ private void SerializeMultidimensionalArray(JsonWriter writer, Array values, Jso writer.WriteEndArray(); } - private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) + private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays); // don't make readonly fields that aren't creator parameters the referenced value because they can't be deserialized to @@ -834,7 +851,7 @@ private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract #if HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE [SecuritySafeCritical] #endif - private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (!JsonTypeReflector.FullyTrusted) { @@ -855,7 +872,7 @@ private void SerializeISerializable(JsonWriter writer, ISerializable value, Json foreach (SerializationEntry serializationEntry in serializationInfo) { - JsonContract valueContract = GetContractSafe(serializationEntry.Value); + JsonContract? valueContract = GetContractSafe(serializationEntry.Value); if (ShouldWriteReference(serializationEntry.Value, null, valueContract, contract, member)) { @@ -877,7 +894,7 @@ private void SerializeISerializable(JsonWriter writer, ISerializable value, Json #endif #if HAVE_DYNAMIC - private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); @@ -895,7 +912,7 @@ private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider valu { try { - if (!CalculatePropertyValues(writer, value, contract, member, property, out JsonContract memberContract, out object memberValue)) + if (!CalculatePropertyValues(writer, value, contract, member, property, out JsonContract? memberContract, out object? memberValue)) { continue; } @@ -919,11 +936,11 @@ private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider valu foreach (string memberName in value.GetDynamicMemberNames()) { - if (contract.TryGetMember(value, memberName, out object memberValue)) + if (contract.TryGetMember(value, memberName, out object? memberValue)) { try { - JsonContract valueContract = GetContractSafe(memberValue); + JsonContract? valueContract = GetContractSafe(memberValue); if (!ShouldWriteDynamicProperty(memberValue)) { @@ -961,7 +978,7 @@ private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider valu } #endif - private bool ShouldWriteDynamicProperty(object memberValue) + private bool ShouldWriteDynamicProperty(object? memberValue) { if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null) { @@ -977,7 +994,7 @@ private bool ShouldWriteDynamicProperty(object memberValue) return true; } - private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty) + private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { TypeNameHandling resolvedTypeNameHandling = member?.TypeNameHandling @@ -995,7 +1012,7 @@ private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract { if (member != null) { - if (contract.NonNullableUnderlyingType != member.PropertyContract.CreatedType) + if (contract.NonNullableUnderlyingType != member.PropertyContract!.CreatedType) { return true; } @@ -1021,8 +1038,9 @@ private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract return false; } - private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) + private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { +#pragma warning disable CS8600, CS8602, CS8604 object underlyingDictionary = values is IWrappedDictionary wrappedDictionary ? wrappedDictionary.UnderlyingDictionary : values; OnSerializing(writer, contract, underlyingDictionary); @@ -1059,7 +1077,7 @@ private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDict try { object value = entry.Value; - JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); + JsonContract? valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { @@ -1101,6 +1119,7 @@ private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDict _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, underlyingDictionary); +#pragma warning restore CS8600, CS8602, CS8604 } private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape) @@ -1150,7 +1169,7 @@ private string GetPropertyName(JsonWriter writer, object name, JsonContract cont { escape = true; - if (primitiveContract.IsEnum && EnumUtils.TryToString(primitiveContract.NonNullableUnderlyingType, name, null, out string enumName)) + if (primitiveContract.IsEnum && EnumUtils.TryToString(primitiveContract.NonNullableUnderlyingType, name, null, out string? enumName)) { return enumName; } @@ -1159,7 +1178,7 @@ private string GetPropertyName(JsonWriter writer, object name, JsonContract cont } } } - else if (TryConvertToString(name, name.GetType(), out string propertyName)) + else if (TryConvertToString(name, name.GetType(), out string? propertyName)) { escape = true; return propertyName; diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index a5ff8c052..29cac8370 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -34,8 +34,8 @@ namespace Newtonsoft.Json.Serialization { internal class JsonSerializerProxy : JsonSerializer { - private readonly JsonSerializerInternalReader _serializerReader; - private readonly JsonSerializerInternalWriter _serializerWriter; + private readonly JsonSerializerInternalReader? _serializerReader; + private readonly JsonSerializerInternalWriter? _serializerWriter; private readonly JsonSerializer _serializer; public override event EventHandler Error @@ -44,19 +44,19 @@ public override event EventHandler Error remove => _serializer.Error -= value; } - public override IReferenceResolver ReferenceResolver + public override IReferenceResolver? ReferenceResolver { get => _serializer.ReferenceResolver; set => _serializer.ReferenceResolver = value; } - public override ITraceWriter TraceWriter + public override ITraceWriter? TraceWriter { get => _serializer.TraceWriter; set => _serializer.TraceWriter = value; } - public override IEqualityComparer EqualityComparer + public override IEqualityComparer? EqualityComparer { get => _serializer.EqualityComparer; set => _serializer.EqualityComparer = value; @@ -230,7 +230,7 @@ internal JsonSerializerInternalBase GetInternalSerializer() } else { - return _serializerWriter; + return _serializerWriter!; } } @@ -250,7 +250,7 @@ public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter) _serializer = serializerWriter.Serializer; } - internal override object DeserializeInternal(JsonReader reader, Type objectType) + internal override object? DeserializeInternal(JsonReader reader, Type? objectType) { if (_serializerReader != null) { @@ -274,7 +274,7 @@ internal override void PopulateInternal(JsonReader reader, object target) } } - internal override void SerializeInternal(JsonWriter jsonWriter, object value, Type rootType) + internal override void SerializeInternal(JsonWriter jsonWriter, object? value, Type? rootType) { if (_serializerWriter != null) { diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 25100201b..b83bcbade 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -58,15 +58,15 @@ internal static class JsonTypeReflector public const string ConcurrentDictionaryTypeName = "System.Collections.Concurrent.ConcurrentDictionary`2"; - private static readonly ThreadSafeStore> CreatorCache = - new ThreadSafeStore>(GetCreator); + private static readonly ThreadSafeStore> CreatorCache = + new ThreadSafeStore>(GetCreator); #if !(NET20 || DOTNET) - private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); + private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); private static ReflectionObject _metadataTypeAttributeReflectionObject; #endif - public static T GetCachedAttribute(object attributeProvider) where T : Attribute + public static T? GetCachedAttribute(object attributeProvider) where T : Attribute { return CachedAttributeGetter.GetAttribute(attributeProvider); } @@ -96,14 +96,14 @@ public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter t #endif #if HAVE_DATA_CONTRACTS - public static DataContractAttribute GetDataContractAttribute(Type type) + public static DataContractAttribute? GetDataContractAttribute(Type type) { // DataContractAttribute does not have inheritance Type currentType = type; while (currentType != null) { - DataContractAttribute result = CachedAttributeGetter.GetAttribute(currentType); + DataContractAttribute? result = CachedAttributeGetter.GetAttribute(currentType); if (result != null) { return result; @@ -115,7 +115,7 @@ public static DataContractAttribute GetDataContractAttribute(Type type) return null; } - public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo) + public static DataMemberAttribute? GetDataMemberAttribute(MemberInfo memberInfo) { // DataMemberAttribute does not have inheritance @@ -127,7 +127,7 @@ public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo) // search property and then search base properties if nothing is returned and the property is virtual PropertyInfo propertyInfo = (PropertyInfo)memberInfo; - DataMemberAttribute result = CachedAttributeGetter.GetAttribute(propertyInfo); + DataMemberAttribute? result = CachedAttributeGetter.GetAttribute(propertyInfo); if (result == null) { if (propertyInfo.IsVirtual()) @@ -153,14 +153,14 @@ public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo) public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute) { - JsonObjectAttribute objectAttribute = GetCachedAttribute(objectType); + JsonObjectAttribute? objectAttribute = GetCachedAttribute(objectType); if (objectAttribute != null) { return objectAttribute.MemberSerialization; } #if HAVE_DATA_CONTRACTS - DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType); + DataContractAttribute? dataContractAttribute = GetDataContractAttribute(objectType); if (dataContractAttribute != null) { return MemberSerialization.OptIn; @@ -178,13 +178,13 @@ public static MemberSerialization GetObjectMemberSerialization(Type objectType, return MemberSerialization.OptOut; } - public static JsonConverter GetJsonConverter(object attributeProvider) + public static JsonConverter? GetJsonConverter(object attributeProvider) { - JsonConverterAttribute converterAttribute = GetCachedAttribute(attributeProvider); + JsonConverterAttribute? converterAttribute = GetCachedAttribute(attributeProvider); if (converterAttribute != null) { - Func creator = CreatorCache.Get(converterAttribute.ConverterType); + Func creator = CreatorCache.Get(converterAttribute.ConverterType); if (creator != null) { return (JsonConverter)creator(converterAttribute.ConverterParameters); @@ -200,19 +200,19 @@ public static JsonConverter GetJsonConverter(object attributeProvider) /// The type to create. /// Optional arguments to pass to an initializing constructor of the JsonConverter. /// If null, the default constructor is used. - public static JsonConverter CreateJsonConverterInstance(Type converterType, object[] args) + public static JsonConverter CreateJsonConverterInstance(Type converterType, object[]? args) { - Func converterCreator = CreatorCache.Get(converterType); + Func converterCreator = CreatorCache.Get(converterType); return (JsonConverter)converterCreator(args); } - public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyType, object[] args) + public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyType, object[]? args) { - Func converterCreator = CreatorCache.Get(namingStrategyType); + Func converterCreator = CreatorCache.Get(namingStrategyType); return (NamingStrategy)converterCreator(args); } - public static NamingStrategy GetContainerNamingStrategy(JsonContainerAttribute containerAttribute) + public static NamingStrategy? GetContainerNamingStrategy(JsonContainerAttribute containerAttribute) { if (containerAttribute.NamingStrategyInstance == null) { @@ -227,9 +227,9 @@ public static NamingStrategy GetContainerNamingStrategy(JsonContainerAttribute c return containerAttribute.NamingStrategyInstance; } - private static Func GetCreator(Type type) + private static Func GetCreator(Type type) { - Func defaultConstructor = (ReflectionUtils.HasDefaultConstructor(type, false)) + Func? defaultConstructor = (ReflectionUtils.HasDefaultConstructor(type, false)) ? ReflectionDelegateFactory.CreateDefaultConstructor(type) : null; @@ -276,12 +276,12 @@ private static Func GetCreator(Type type) } #if !(NET20 || DOTNET) - private static Type GetAssociatedMetadataType(Type type) + private static Type? GetAssociatedMetadataType(Type type) { return AssociatedMetadataTypesCache.Get(type); } - private static Type GetAssociateMetadataTypeFromAttribute(Type type) + private static Type? GetAssociateMetadataTypeFromAttribute(Type type) { Attribute[] customAttributes = ReflectionUtils.GetAttributes(type, null, true); @@ -300,7 +300,7 @@ private static Type GetAssociateMetadataTypeFromAttribute(Type type) _metadataTypeAttributeReflectionObject = ReflectionObject.Create(attributeType, metadataClassTypeName); } - return (Type)_metadataTypeAttributeReflectionObject.GetValue(attribute, metadataClassTypeName); + return (Type?)_metadataTypeAttributeReflectionObject.GetValue(attribute, metadataClassTypeName); } } @@ -308,12 +308,12 @@ private static Type GetAssociateMetadataTypeFromAttribute(Type type) } #endif - private static T GetAttribute(Type type) where T : Attribute + private static T? GetAttribute(Type type) where T : Attribute { - T attribute; + T? attribute; #if !(NET20 || DOTNET) - Type metadataType = GetAssociatedMetadataType(type); + Type? metadataType = GetAssociatedMetadataType(type); if (metadataType != null) { attribute = ReflectionUtils.GetAttribute(metadataType, true); @@ -342,12 +342,12 @@ private static T GetAttribute(Type type) where T : Attribute return null; } - private static T GetAttribute(MemberInfo memberInfo) where T : Attribute + private static T? GetAttribute(MemberInfo memberInfo) where T : Attribute { - T attribute; + T? attribute; #if !(NET20 || DOTNET) - Type metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); + Type? metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); if (metadataType != null) { MemberInfo metadataTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(metadataType, memberInfo); @@ -423,7 +423,7 @@ public static bool IsSerializable(object provider) } #endif - public static T GetAttribute(object provider) where T : Attribute + public static T? GetAttribute(object provider) where T : Attribute { if (provider is Type type) { diff --git a/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs b/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs index 6816b6568..a2672ed20 100644 --- a/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs @@ -41,7 +41,7 @@ public MemoryTraceWriter() /// The at which to write this trace. /// The trace message. /// The trace exception. This parameter is optional. - public void Trace(TraceLevel level, string message, Exception ex) + public void Trace(TraceLevel level, string message, Exception? ex) { StringBuilder sb = new StringBuilder(); sb.Append(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture)); diff --git a/Src/Newtonsoft.Json/Serialization/NamingStrategy.cs b/Src/Newtonsoft.Json/Serialization/NamingStrategy.cs index 461bad93e..88118844f 100644 --- a/Src/Newtonsoft.Json/Serialization/NamingStrategy.cs +++ b/Src/Newtonsoft.Json/Serialization/NamingStrategy.cs @@ -130,7 +130,7 @@ public override int GetHashCode() /// /// /// - protected bool Equals(NamingStrategy other) + protected bool Equals(NamingStrategy? other) { if (other == null) { diff --git a/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs b/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs index 380674fe1..a6945e747 100644 --- a/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs +++ b/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs @@ -29,5 +29,5 @@ namespace Newtonsoft.Json.Serialization /// Represents a method that constructs an object. /// /// The object type to create. - public delegate object ObjectConstructor(params object[] args); + public delegate object ObjectConstructor(params object?[] args); } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs b/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs index 9c3a657ae..7ad281b56 100644 --- a/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs +++ b/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs @@ -52,7 +52,7 @@ public ReflectionValueProvider(MemberInfo memberInfo) /// /// The target to set the value on. /// The value to set on the target. - public void SetValue(object target, object value) + public void SetValue(object target, object? value) { try { @@ -69,7 +69,7 @@ public void SetValue(object target, object value) /// /// The target to get the value from. /// The value. - public object GetValue(object target) + public object? GetValue(object target) { try { diff --git a/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs b/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs index 033692c49..6a960a3d6 100644 --- a/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs +++ b/Src/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs @@ -41,12 +41,12 @@ public SerializationBinderAdapter(SerializationBinder serializationBinder) } #pragma warning restore 618 - public Type BindToType(string assemblyName, string typeName) + public Type BindToType(string? assemblyName, string typeName) { return SerializationBinder.BindToType(assemblyName, typeName); } - public void BindToName(Type serializedType, out string assemblyName, out string typeName) + public void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { #if HAVE_SERIALIZATION_BINDER_BIND_TO_NAME SerializationBinder.BindToName(serializedType, out assemblyName, out typeName); diff --git a/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs b/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs index 5dbbd5de7..04bc99ea3 100644 --- a/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs +++ b/Src/Newtonsoft.Json/Serialization/TraceJsonReader.cs @@ -68,16 +68,16 @@ public override bool Read() return value; } - public override string ReadAsString() + public override string? ReadAsString() { - string value = _innerReader.ReadAsString(); + string? value = _innerReader.ReadAsString(); WriteCurrentToken(); return value; } - public override byte[] ReadAsBytes() + public override byte[]? ReadAsBytes() { - byte[] value = _innerReader.ReadAsBytes(); + byte[]? value = _innerReader.ReadAsBytes(); WriteCurrentToken(); return value; } @@ -136,9 +136,9 @@ public override char QuoteChar public override JsonToken TokenType => _innerReader.TokenType; - public override object Value => _innerReader.Value; + public override object? Value => _innerReader.Value; - public override Type ValueType => _innerReader.ValueType; + public override Type ?ValueType => _innerReader.ValueType; public override void Close() { diff --git a/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs b/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs index 95d9ebae2..b660b07f7 100644 --- a/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/TraceJsonWriter.cs @@ -144,7 +144,7 @@ public override void WriteValue(char? value) } } - public override void WriteValue(byte[] value) + public override void WriteValue(byte[]? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); @@ -321,7 +321,7 @@ public override void WriteValue(long? value) } } - public override void WriteValue(object value) + public override void WriteValue(object? value) { #if HAVE_BIG_INTEGER if (value is BigInteger) @@ -389,7 +389,7 @@ public override void WriteValue(short? value) } } - public override void WriteValue(string value) + public override void WriteValue(string? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); @@ -459,7 +459,7 @@ public override void WriteValue(ulong? value) } } - public override void WriteValue(Uri value) + public override void WriteValue(Uri? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); @@ -501,7 +501,7 @@ public override void WriteWhitespace(string ws) base.WriteWhitespace(ws); } - public override void WriteComment(string text) + public override void WriteComment(string? text) { _textWriter.WriteComment(text); _innerWriter.WriteComment(text); @@ -566,7 +566,7 @@ public override void WriteEndObject() base.WriteEndObject(); } - public override void WriteRawValue(string json) + public override void WriteRawValue(string? json) { _textWriter.WriteRawValue(json); _innerWriter.WriteRawValue(json); @@ -575,7 +575,7 @@ public override void WriteRawValue(string json) InternalWriteValue(JsonToken.Undefined); } - public override void WriteRaw(string json) + public override void WriteRaw(string? json) { _textWriter.WriteRaw(json); _innerWriter.WriteRaw(json); diff --git a/Src/Newtonsoft.Json/SerializationBinder.cs b/Src/Newtonsoft.Json/SerializationBinder.cs index b3e480f08..9a6193c06 100644 --- a/Src/Newtonsoft.Json/SerializationBinder.cs +++ b/Src/Newtonsoft.Json/SerializationBinder.cs @@ -17,7 +17,7 @@ public abstract class SerializationBinder /// Specifies the name of the serialized object. /// Specifies the name of the serialized object /// The type of the object the formatter creates a new instance of. - public abstract Type BindToType(string assemblyName, string typeName); + public abstract Type BindToType(string? assemblyName, string typeName); /// /// When overridden in a derived class, controls the binding of a serialized object to a type. @@ -25,7 +25,7 @@ public abstract class SerializationBinder /// The type of the object the formatter creates a new instance of. /// Specifies the name of the serialized object. /// Specifies the name of the serialized object. - public virtual void BindToName(Type serializedType, out string assemblyName, out string typeName) + public virtual void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { assemblyName = null; typeName = null; diff --git a/Src/Newtonsoft.Json/Utilities/AsyncUtils.cs b/Src/Newtonsoft.Json/Utilities/AsyncUtils.cs index 49cbad97e..ebcd7b057 100644 --- a/Src/Newtonsoft.Json/Utilities/AsyncUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/AsyncUtils.cs @@ -40,12 +40,12 @@ internal static class AsyncUtils internal static Task ToAsync(this bool value) => value ? True : False; - public static Task CancelIfRequestedAsync(this CancellationToken cancellationToken) + public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : null; } - public static Task CancelIfRequestedAsync(this CancellationToken cancellationToken) + public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : null; } @@ -61,7 +61,9 @@ public static Task FromCanceled(this CancellationToken cancellationToken) public static Task FromCanceled(this CancellationToken cancellationToken) { Debug.Assert(cancellationToken.IsCancellationRequested); +#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. return new Task(() => default, cancellationToken); +#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. } // Task.Delay(0) is optimised as a cached task within the framework, and indeed @@ -75,7 +77,7 @@ public static Task WriteAsync(this TextWriter writer, char value, CancellationTo return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : writer.WriteAsync(value); } - public static Task WriteAsync(this TextWriter writer, string value, CancellationToken cancellationToken) + public static Task WriteAsync(this TextWriter writer, string? value, CancellationToken cancellationToken) { Debug.Assert(writer != null); return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : writer.WriteAsync(value); diff --git a/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs b/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs index b65465eac..c1dd16d11 100644 --- a/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs +++ b/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs @@ -40,7 +40,7 @@ internal class Base64Encoder private readonly char[] _charsLine = new char[Base64LineSize]; private readonly TextWriter _writer; - private byte[] _leftOverBytes; + private byte[]? _leftOverBytes; private int _leftOverBytesCount; public Base64Encoder(TextWriter writer) @@ -128,7 +128,7 @@ private bool FulfillFromLeftover(byte[] buffer, int index, ref int count) int leftOverBytesCount = _leftOverBytesCount; while (leftOverBytesCount < 3 && count > 0) { - _leftOverBytes[leftOverBytesCount++] = buffer[index++]; + _leftOverBytes![leftOverBytesCount++] = buffer[index++]; count--; } diff --git a/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs b/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs index 3ee3c5969..2f97c0b95 100644 --- a/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs +++ b/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs @@ -63,7 +63,7 @@ public void Set(TFirst first, TSecond second) { if (_firstToSecond.TryGetValue(first, out TSecond existingSecond)) { - if (!existingSecond.Equals(second)) + if (!existingSecond!.Equals(second)) { throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first)); } @@ -71,7 +71,7 @@ public void Set(TFirst first, TSecond second) if (_secondToFirst.TryGetValue(second, out TFirst existingFirst)) { - if (!existingFirst.Equals(first)) + if (!existingFirst!.Equals(first)) { throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second)); } diff --git a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs index 59694ac09..0061d7bef 100644 --- a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs @@ -116,17 +116,17 @@ public static bool IsDictionaryType(Type type) return false; } - public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) + public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) { Type genericConstructorArgument = typeof(IList<>).MakeGenericType(collectionItemType); return ResolveEnumerableCollectionConstructor(collectionType, collectionItemType, genericConstructorArgument); } - public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, Type constructorArgumentType) + public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, Type constructorArgumentType) { Type genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType); - ConstructorInfo match = null; + ConstructorInfo? match = null; foreach (ConstructorInfo constructor in collectionType.GetConstructors(BindingFlags.Public | BindingFlags.Instance)) { @@ -248,6 +248,7 @@ public static int IndexOfReference(this List list, T item) return i; } } + return -1; } @@ -378,7 +379,7 @@ public static Array ToMultidimensionalArray(IList values, Type type, int rank) #endif public static T[] ArrayEmpty() { - T[] array = Enumerable.Empty() as T[]; + T[]? array = Enumerable.Empty() as T[]; Debug.Assert(array != null); // Defensively guard against a version of Linq where Enumerable.Empty doesn't // return an array, but throw in debug versions so a better strategy can be diff --git a/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs b/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs index a1696670f..ebb79f235 100644 --- a/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs +++ b/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs @@ -44,9 +44,9 @@ internal interface IWrappedCollection : IList internal class CollectionWrapper : ICollection, IWrappedCollection { - private readonly IList _list; - private readonly ICollection _genericCollection; - private object _syncRoot; + private readonly IList? _list; + private readonly ICollection? _genericCollection; + private object? _syncRoot; public CollectionWrapper(IList list) { @@ -77,7 +77,7 @@ public virtual void Add(T item) } else { - _list.Add(item); + _list!.Add(item); } } @@ -89,7 +89,7 @@ public virtual void Clear() } else { - _list.Clear(); + _list!.Clear(); } } @@ -101,7 +101,7 @@ public virtual bool Contains(T item) } else { - return _list.Contains(item); + return _list!.Contains(item); } } @@ -113,7 +113,7 @@ public virtual void CopyTo(T[] array, int arrayIndex) } else { - _list.CopyTo(array, arrayIndex); + _list!.CopyTo(array, arrayIndex); } } @@ -127,7 +127,7 @@ public virtual int Count } else { - return _list.Count; + return _list!.Count; } } } @@ -142,7 +142,7 @@ public virtual bool IsReadOnly } else { - return _list.IsReadOnly; + return _list!.IsReadOnly; } } } @@ -155,11 +155,11 @@ public virtual bool Remove(T item) } else { - bool contains = _list.Contains(item); + bool contains = _list!.Contains(item); if (contains) { - _list.Remove(item); + _list!.Remove(item); } return contains; @@ -173,7 +173,7 @@ public virtual IEnumerator GetEnumerator() IEnumerator IEnumerable.GetEnumerator() { - return ((IEnumerable)_genericCollection ?? _list).GetEnumerator(); + return ((IEnumerable)_genericCollection! ?? _list!).GetEnumerator(); } int IList.Add(object value) @@ -203,7 +203,7 @@ int IList.IndexOf(object value) if (IsCompatibleObject(value)) { - return _list.IndexOf((T)value); + return _list!.IndexOf((T)value); } return -1; @@ -216,7 +216,7 @@ void IList.RemoveAt(int index) throw new InvalidOperationException("Wrapped ICollection does not support RemoveAt."); } - _list.RemoveAt(index); + _list!.RemoveAt(index); } void IList.Insert(int index, object value) @@ -227,7 +227,7 @@ void IList.Insert(int index, object value) } VerifyValueType(value); - _list.Insert(index, (T)value); + _list!.Insert(index, (T)value); } bool IList.IsFixedSize @@ -241,7 +241,7 @@ bool IList.IsFixedSize } else { - return _list.IsFixedSize; + return _list!.IsFixedSize; } } } @@ -263,7 +263,7 @@ object IList.this[int index] throw new InvalidOperationException("Wrapped ICollection does not support indexer."); } - return _list[index]; + return _list![index]; } set { @@ -273,7 +273,7 @@ object IList.this[int index] } VerifyValueType(value); - _list[index] = (T)value; + _list![index] = (T)value; } } @@ -315,6 +315,6 @@ private static bool IsCompatibleObject(object value) return true; } - public object UnderlyingCollection => (object)_genericCollection ?? _list; + public object UnderlyingCollection => (object)_genericCollection! ?? _list!; } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index f00d89478..364088e28 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -27,6 +27,7 @@ using System.Collections.Generic; using System.Globalization; using System.ComponentModel; +using System.Runtime.CompilerServices; #if HAVE_BIG_INTEGER using System.Numerics; #endif @@ -36,6 +37,7 @@ #endif using Newtonsoft.Json.Serialization; using System.Reflection; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #endif @@ -94,8 +96,14 @@ internal enum PrimitiveTypeCode internal class TypeInformation { - public Type Type { get; set; } - public PrimitiveTypeCode TypeCode { get; set; } + public Type Type { get; } + public PrimitiveTypeCode TypeCode { get; } + + public TypeInformation(Type type, PrimitiveTypeCode typeCode) + { + Type = type; + TypeCode = typeCode; + } } internal enum ParseResult @@ -163,25 +171,25 @@ internal static class ConvertUtils private static readonly TypeInformation[] PrimitiveTypeCodes = { // need all of these. lookup against the index with TypeCode value - new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, - new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Object }, - new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.DBNull }, - new TypeInformation { Type = typeof(bool), TypeCode = PrimitiveTypeCode.Boolean }, - new TypeInformation { Type = typeof(char), TypeCode = PrimitiveTypeCode.Char }, - new TypeInformation { Type = typeof(sbyte), TypeCode = PrimitiveTypeCode.SByte }, - new TypeInformation { Type = typeof(byte), TypeCode = PrimitiveTypeCode.Byte }, - new TypeInformation { Type = typeof(short), TypeCode = PrimitiveTypeCode.Int16 }, - new TypeInformation { Type = typeof(ushort), TypeCode = PrimitiveTypeCode.UInt16 }, - new TypeInformation { Type = typeof(int), TypeCode = PrimitiveTypeCode.Int32 }, - new TypeInformation { Type = typeof(uint), TypeCode = PrimitiveTypeCode.UInt32 }, - new TypeInformation { Type = typeof(long), TypeCode = PrimitiveTypeCode.Int64 }, - new TypeInformation { Type = typeof(ulong), TypeCode = PrimitiveTypeCode.UInt64 }, - new TypeInformation { Type = typeof(float), TypeCode = PrimitiveTypeCode.Single }, - new TypeInformation { Type = typeof(double), TypeCode = PrimitiveTypeCode.Double }, - new TypeInformation { Type = typeof(decimal), TypeCode = PrimitiveTypeCode.Decimal }, - new TypeInformation { Type = typeof(DateTime), TypeCode = PrimitiveTypeCode.DateTime }, - new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, // no 17 in TypeCode for some reason - new TypeInformation { Type = typeof(string), TypeCode = PrimitiveTypeCode.String } + new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), + new TypeInformation(typeof(object), PrimitiveTypeCode.Object), + new TypeInformation(typeof(object), PrimitiveTypeCode.DBNull), + new TypeInformation(typeof(bool), PrimitiveTypeCode.Boolean), + new TypeInformation(typeof(char), PrimitiveTypeCode.Char), + new TypeInformation(typeof(sbyte), PrimitiveTypeCode.SByte), + new TypeInformation(typeof(byte), PrimitiveTypeCode.Byte), + new TypeInformation(typeof(short), PrimitiveTypeCode.Int16), + new TypeInformation(typeof(ushort), PrimitiveTypeCode.UInt16), + new TypeInformation(typeof(int), PrimitiveTypeCode.Int32), + new TypeInformation(typeof(uint), PrimitiveTypeCode.UInt32), + new TypeInformation(typeof(long), PrimitiveTypeCode.Int64), + new TypeInformation(typeof(ulong), PrimitiveTypeCode.UInt64), + new TypeInformation(typeof(float), PrimitiveTypeCode.Single), + new TypeInformation(typeof(double), PrimitiveTypeCode.Double), + new TypeInformation(typeof(decimal), PrimitiveTypeCode.Decimal), + new TypeInformation(typeof(DateTime), PrimitiveTypeCode.DateTime), + new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), // no 17 in TypeCode for some reason + new TypeInformation(typeof(string), PrimitiveTypeCode.String) }; #endif @@ -248,10 +256,10 @@ public static TimeSpan ParseTimeSpan(string input) #endif } - private static readonly ThreadSafeStore, Func> CastConverters = - new ThreadSafeStore, Func>(CreateCastConverter); + private static readonly ThreadSafeStore, Func?> CastConverters = + new ThreadSafeStore, Func?>(CreateCastConverter); - private static Func CreateCastConverter(StructMultiKey t) + private static Func? CreateCastConverter(StructMultiKey t) { Type initialType = t.Value1; Type targetType = t.Value2; @@ -263,7 +271,7 @@ private static Func CreateCastConverter(StructMultiKey call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(castMethodInfo); + MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(castMethodInfo); return o => call(null, o); } @@ -363,10 +371,10 @@ internal enum ConvertResult public static object Convert(object initialValue, CultureInfo culture, Type targetType) { - switch (TryConvertInternal(initialValue, culture, targetType, out object value)) + switch (TryConvertInternal(initialValue, culture, targetType, out object? value)) { case ConvertResult.Success: - return value; + return value!; case ConvertResult.CannotConvertNull: throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)); case ConvertResult.NotInstantiableType: @@ -378,7 +386,7 @@ public static object Convert(object initialValue, CultureInfo culture, Type targ } } - private static bool TryConvert(object initialValue, CultureInfo culture, Type targetType, out object value) + private static bool TryConvert(object? initialValue, CultureInfo culture, Type targetType, out object? value) { try { @@ -397,7 +405,7 @@ private static bool TryConvert(object initialValue, CultureInfo culture, Type ta } } - private static ConvertResult TryConvertInternal(object initialValue, CultureInfo culture, Type targetType, out object value) + private static ConvertResult TryConvertInternal(object? initialValue, CultureInfo culture, Type targetType, out object? value) { if (initialValue == null) { @@ -482,7 +490,7 @@ private static ConvertResult TryConvertInternal(object initialValue, CultureInfo } if (targetType == typeof(Version)) { - if (VersionTryParse(s, out Version result)) + if (VersionTryParse(s, out Version? result)) { value = result; return ConvertResult.Success; @@ -567,7 +575,7 @@ private static ConvertResult TryConvertInternal(object initialValue, CultureInfo /// The converted type. If conversion was unsuccessful, the initial value /// is returned if assignable to the target type. /// - public static object ConvertOrCast(object initialValue, CultureInfo culture, Type targetType) + public static object? ConvertOrCast(object? initialValue, CultureInfo culture, Type targetType) { if (targetType == typeof(object)) { @@ -579,27 +587,27 @@ public static object ConvertOrCast(object initialValue, CultureInfo culture, Typ return null; } - if (TryConvert(initialValue, culture, targetType, out object convertedValue)) + if (TryConvert(initialValue, culture, targetType, out object? convertedValue)) { return convertedValue; } - return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue), targetType); + return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue)!, targetType); } #endregion - private static object EnsureTypeAssignable(object value, Type initialType, Type targetType) + private static object? EnsureTypeAssignable(object? value, Type initialType, Type targetType) { - Type valueType = value?.GetType(); - if (value != null) { + Type valueType = value.GetType(); + if (targetType.IsAssignableFrom(valueType)) { return value; } - Func castConverter = CastConverters.Get(new StructMultiKey(valueType, targetType)); + Func? castConverter = CastConverters.Get(new StructMultiKey(valueType, targetType)); if (castConverter != null) { return castConverter(value); @@ -616,7 +624,7 @@ private static object EnsureTypeAssignable(object value, Type initialType, Type throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialType?.ToString() ?? "{null}", targetType)); } - public static bool VersionTryParse(string input, out Version result) + public static bool VersionTryParse(string input, [NotNullWhen(true)]out Version? result) { #if HAVE_VERSION_TRY_PARSE return Version.TryParse(input, out result); diff --git a/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs index 34e65a343..c1cd79e82 100644 --- a/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs @@ -341,7 +341,7 @@ private static DateTime CreateDateTime(DateTimeParser dateTimeParser) return d; } - internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt) + internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { @@ -377,7 +377,7 @@ internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling da return false; } - internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt) + internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { @@ -414,7 +414,7 @@ internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZon } #if HAVE_DATE_TIME_OFFSET - internal static bool TryParseDateTimeOffset(StringReference s, string dateFormatString, CultureInfo culture, out DateTimeOffset dt) + internal static bool TryParseDateTimeOffset(StringReference s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { @@ -450,7 +450,7 @@ internal static bool TryParseDateTimeOffset(StringReference s, string dateFormat return false; } - internal static bool TryParseDateTimeOffset(string s, string dateFormatString, CultureInfo culture, out DateTimeOffset dt) + internal static bool TryParseDateTimeOffset(string s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { @@ -618,7 +618,7 @@ private static bool TryReadOffset(StringReference offsetText, int startIndex, ou #endregion #region Write - internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string formatString, CultureInfo culture) + internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (string.IsNullOrEmpty(formatString)) { @@ -751,7 +751,7 @@ internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset } #if HAVE_DATE_TIME_OFFSET - internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string formatString, CultureInfo culture) + internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (string.IsNullOrEmpty(formatString)) { diff --git a/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs b/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs index 78cea5e2a..19a7a322a 100644 --- a/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs +++ b/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs @@ -27,11 +27,13 @@ using System.Collections.Generic; using System.Collections; using System.Threading; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; - #endif namespace Newtonsoft.Json.Utilities @@ -44,12 +46,12 @@ internal interface IWrappedDictionary internal class DictionaryWrapper : IDictionary, IWrappedDictionary { - private readonly IDictionary _dictionary; - private readonly IDictionary _genericDictionary; + private readonly IDictionary? _dictionary; + private readonly IDictionary? _genericDictionary; #if HAVE_READ_ONLY_COLLECTIONS - private readonly IReadOnlyDictionary _readOnlyDictionary; + private readonly IReadOnlyDictionary? _readOnlyDictionary; #endif - private object _syncRoot; + private object? _syncRoot; public DictionaryWrapper(IDictionary dictionary) { @@ -74,6 +76,15 @@ public DictionaryWrapper(IReadOnlyDictionary dictionary) } #endif + internal IDictionary GenericDictionary + { + get + { + Debug.Assert(_genericDictionary != null); + return _genericDictionary; + } + } + public void Add(TKey key, TValue value) { if (_dictionary != null) @@ -104,7 +115,7 @@ public bool ContainsKey(TKey key) #endif else { - return _genericDictionary.ContainsKey(key); + return GenericDictionary.ContainsKey(key); } } @@ -124,7 +135,7 @@ public ICollection Keys #endif else { - return _genericDictionary.Keys; + return GenericDictionary.Keys; } } } @@ -151,17 +162,19 @@ public bool Remove(TKey key) #endif else { - return _genericDictionary.Remove(key); + return GenericDictionary.Remove(key); } } - public bool TryGetValue(TKey key, out TValue value) + public bool TryGetValue(TKey key, [MaybeNull]out TValue value) { if (_dictionary != null) { if (!_dictionary.Contains(key)) { +#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. value = default; +#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. return false; } else @@ -178,7 +191,7 @@ public bool TryGetValue(TKey key, out TValue value) #endif else { - return _genericDictionary.TryGetValue(key, out value); + return GenericDictionary.TryGetValue(key, out value); } } @@ -198,7 +211,7 @@ public ICollection Values #endif else { - return _genericDictionary.Values; + return GenericDictionary.Values; } } } @@ -219,7 +232,7 @@ public TValue this[TKey key] #endif else { - return _genericDictionary[key]; + return GenericDictionary[key]; } } set @@ -236,7 +249,7 @@ public TValue this[TKey key] #endif else { - _genericDictionary[key] = value; + GenericDictionary[key] = value; } } } @@ -273,7 +286,7 @@ public void Clear() #endif else { - _genericDictionary.Clear(); + GenericDictionary.Clear(); } } @@ -291,7 +304,7 @@ public bool Contains(KeyValuePair item) #endif else { - return _genericDictionary.Contains(item); + return GenericDictionary.Contains(item); } } @@ -322,7 +335,7 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) #endif else { - _genericDictionary.CopyTo(array, arrayIndex); + GenericDictionary.CopyTo(array, arrayIndex); } } @@ -342,7 +355,7 @@ public int Count #endif else { - return _genericDictionary.Count; + return GenericDictionary.Count; } } } @@ -363,7 +376,7 @@ public bool IsReadOnly #endif else { - return _genericDictionary.IsReadOnly; + return GenericDictionary.IsReadOnly; } } } @@ -399,7 +412,7 @@ public bool Remove(KeyValuePair item) #endif else { - return _genericDictionary.Remove(item); + return GenericDictionary.Remove(item); } } @@ -417,7 +430,7 @@ public IEnumerator> GetEnumerator() #endif else { - return _genericDictionary.GetEnumerator(); + return GenericDictionary.GetEnumerator(); } } @@ -440,11 +453,11 @@ void IDictionary.Add(object key, object value) #endif else { - _genericDictionary.Add((TKey)key, (TValue)value); + GenericDictionary.Add((TKey)key, (TValue)value); } } - object IDictionary.this[object key] + object? IDictionary.this[object key] { get { @@ -460,7 +473,7 @@ object IDictionary.this[object key] #endif else { - return _genericDictionary[(TKey)key]; + return GenericDictionary[(TKey)key]; } } set @@ -477,7 +490,9 @@ object IDictionary.this[object key] #endif else { - _genericDictionary[(TKey)key] = (TValue)value; +#pragma warning disable CS8601 // Possible null reference assignment. + GenericDictionary[(TKey)key] = (TValue)value; +#pragma warning restore CS8601 // Possible null reference assignment. } } } @@ -525,7 +540,7 @@ IDictionaryEnumerator IDictionary.GetEnumerator() #endif else { - return new DictionaryEnumerator(_genericDictionary.GetEnumerator()); + return new DictionaryEnumerator(GenericDictionary.GetEnumerator()); } } @@ -543,7 +558,7 @@ bool IDictionary.Contains(object key) #endif else { - return _dictionary.Contains(key); + return _dictionary!.Contains(key); } } @@ -563,7 +578,7 @@ bool IDictionary.IsFixedSize #endif else { - return _dictionary.IsFixedSize; + return _dictionary!.IsFixedSize; } } } @@ -584,7 +599,7 @@ ICollection IDictionary.Keys #endif else { - return _dictionary.Keys; + return _dictionary!.Keys; } } } @@ -603,7 +618,7 @@ public void Remove(object key) #endif else { - _genericDictionary.Remove((TKey)key); + GenericDictionary.Remove((TKey)key); } } @@ -623,7 +638,7 @@ ICollection IDictionary.Values #endif else { - return _dictionary.Values; + return _dictionary!.Values; } } } @@ -642,7 +657,7 @@ void ICollection.CopyTo(Array array, int index) #endif else { - _genericDictionary.CopyTo((KeyValuePair[])array, index); + GenericDictionary.CopyTo((KeyValuePair[])array, index); } } @@ -690,7 +705,7 @@ public object UnderlyingDictionary #endif else { - return _genericDictionary; + return GenericDictionary; } } } diff --git a/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs b/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs index caeb9194c..76734ca3b 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs @@ -36,19 +36,19 @@ public virtual IEnumerable GetDynamicMemberNames(T instance) return CollectionUtils.ArrayEmpty(); } - public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object result) + public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object? result) { result = null; return false; } - public virtual bool TryConvert(T instance, ConvertBinder binder, out object result) + public virtual bool TryConvert(T instance, ConvertBinder binder, out object? result) { result = null; return false; } - public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object result) + public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object? result) { result = null; return false; @@ -64,25 +64,25 @@ public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder) return false; } - public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object result) + public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object? result) { result = null; return false; } - public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object result) + public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object? result) { result = null; return false; } - public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object result) + public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object? result) { result = null; return false; } - public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object result) + public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object? result) { result = null; return false; @@ -98,7 +98,7 @@ public virtual bool TrySetMember(T instance, SetMemberBinder binder, object valu return false; } - public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object result) + public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object? result) { result = null; return false; diff --git a/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs b/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs index 56b556560..41286c310 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs @@ -164,7 +164,7 @@ public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, Dyna : base.BindDeleteIndex(binder, indexes); } - private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion); + private delegate DynamicMetaObject Fallback(DynamicMetaObject? errorSuggestion); private static Expression[] NoArgs => CollectionUtils.ArrayEmpty(); @@ -206,7 +206,7 @@ private static ConstantExpression Constant(DynamicMetaObjectBinder binder) /// Helper method for generating a MetaObject which calls a /// specific method on Dynamic that returns a result /// - private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback, Fallback fallbackInvoke = null) + private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback, Fallback? fallbackInvoke = null) { // // First, call fallback to do default binding @@ -217,7 +217,7 @@ private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObj return BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke); } - private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke) + private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, DynamicMetaObject fallbackResult, Fallback? fallbackInvoke) { // // Build a new expression like: diff --git a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs index 10b3e10b6..9905226b0 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs @@ -40,7 +40,7 @@ internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory { internal static DynamicReflectionDelegateFactory Instance { get; } = new DynamicReflectionDelegateFactory(); - private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner) + private static DynamicMethod CreateDynamicMethod(string name, Type? returnType, Type[] parameterTypes, Type owner) { DynamicMethod dynamicMethod = !owner.IsInterface() ? new DynamicMethod(name, returnType, parameterTypes, owner, true) @@ -59,14 +59,14 @@ public override ObjectConstructor CreateParameterizedConstructor(MethodB return (ObjectConstructor)dynamicMethod.CreateDelegate(typeof(ObjectConstructor)); } - public override MethodCall CreateMethodCall(MethodBase method) + public override MethodCall CreateMethodCall(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, generator, 1); - return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); + return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); } private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex) @@ -279,14 +279,14 @@ private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator generator.Return(); } - public override Func CreateGet(PropertyInfo propertyInfo) + public override Func CreateGet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new[] { typeof(T) }, propertyInfo.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateGetPropertyIL(propertyInfo, generator); - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); + return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) @@ -307,12 +307,12 @@ private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator.Return(); } - public override Func CreateGet(FieldInfo fieldInfo) + public override Func CreateGet(FieldInfo fieldInfo) { if (fieldInfo.IsLiteral) { object constantValue = fieldInfo.GetValue(null); - Func getter = o => constantValue; + Func getter = o => constantValue; return getter; } @@ -321,7 +321,7 @@ public override Func CreateGet(FieldInfo fieldInfo) GenerateCreateGetFieldIL(fieldInfo, generator); - return (Func)dynamicMethod.CreateDelegate(typeof(Func)); + return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator) @@ -340,14 +340,14 @@ private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator generator.Return(); } - public override Action CreateSet(FieldInfo fieldInfo) + public override Action CreateSet(FieldInfo fieldInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateSetFieldIL(fieldInfo, generator); - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); + return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator) @@ -372,14 +372,14 @@ internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator g generator.Return(); } - public override Action CreateSet(PropertyInfo propertyInfo) + public override Action CreateSet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateSetPropertyIL(propertyInfo, generator); - return (Action)dynamicMethod.CreateDelegate(typeof(Action)); + return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) diff --git a/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs b/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs index 5822ba082..750cca8ea 100644 --- a/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs @@ -55,8 +55,8 @@ internal static class BinderWrapper private static object _getCSharpArgumentInfoArray; private static object _setCSharpArgumentInfoArray; - private static MethodCall _getMemberCall; - private static MethodCall _setMemberCall; + private static MethodCall _getMemberCall; + private static MethodCall _setMemberCall; private static bool _init; private static void Init() @@ -89,7 +89,7 @@ private static object CreateSharpArgumentInfoArray(params int[] values) for (int i = 0; i < values.Length; i++) { MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) }); - object arg = createArgumentInfoMethod.Invoke(null, new object[] { 0, null }); + object arg = createArgumentInfoMethod.Invoke(null, new object?[] { 0, null }); a.SetValue(arg, i); } @@ -105,10 +105,10 @@ private static void CreateMemberCalls() Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType); MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); - _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getMemberMethod); + _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getMemberMethod); MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); - _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMemberMethod); + _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMemberMethod); } #endif @@ -116,7 +116,7 @@ public static CallSiteBinder GetMember(string name, Type context) { #if !HAVE_REFLECTION_BINDER Init(); - return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray); + return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray)!; #else return Binder.GetMember( CSharpBinderFlags.None, name, context, new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}); @@ -127,7 +127,7 @@ public static CallSiteBinder SetMember(string name, Type context) { #if !HAVE_REFLECTION_BINDER Init(); - return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray); + return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray)!; #else return Binder.SetMember( CSharpBinderFlags.None, name, context, new[] diff --git a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs index 729670be7..11cc4def0 100644 --- a/Src/Newtonsoft.Json/Utilities/EnumUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/EnumUtils.cs @@ -36,6 +36,8 @@ using System.Reflection; using System.Text; using Newtonsoft.Json.Serialization; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace Newtonsoft.Json.Utilities { @@ -44,9 +46,9 @@ internal static class EnumUtils private const char EnumSeparatorChar = ','; private const string EnumSeparatorString = ", "; - private static readonly ThreadSafeStore, EnumInfo> ValuesAndNamesPerEnum = new ThreadSafeStore, EnumInfo>(InitializeValuesAndNames); + private static readonly ThreadSafeStore, EnumInfo> ValuesAndNamesPerEnum = new ThreadSafeStore, EnumInfo>(InitializeValuesAndNames); - private static EnumInfo InitializeValuesAndNames(StructMultiKey key) + private static EnumInfo InitializeValuesAndNames(StructMultiKey key) { Type enumType = key.Value1; string[] names = Enum.GetNames(enumType); @@ -56,7 +58,7 @@ private static EnumInfo InitializeValuesAndNames(StructMultiKey GetFlagsValues(T value) where T : struct // Used by Newtonsoft.Json.Schema private static CamelCaseNamingStrategy _camelCaseNamingStrategy = new CamelCaseNamingStrategy(); - public static bool TryToString(Type enumType, object value, bool camelCase, out string name) + public static bool TryToString(Type enumType, object value, bool camelCase, [NotNullWhen(true)]out string? name) { return TryToString(enumType, value, camelCase ? _camelCaseNamingStrategy : null, out name); } - public static bool TryToString(Type enumType, object value, NamingStrategy namingStrategy, out string name) + public static bool TryToString(Type enumType, object value, NamingStrategy? namingStrategy, [NotNullWhen(true)]out string? name) { - EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); + EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); ulong v = ToUInt64(value); if (!enumInfo.IsFlags) @@ -149,7 +151,7 @@ public static bool TryToString(Type enumType, object value, NamingStrategy namin } } - private static string InternalFlagsFormat(EnumInfo entry, ulong result) + private static string? InternalFlagsFormat(EnumInfo entry, ulong result) { string[] resolvedNames = entry.ResolvedNames; ulong[] values = entry.Values; @@ -185,7 +187,7 @@ private static string InternalFlagsFormat(EnumInfo entry, ulong result) index--; } - string returnString; + string? returnString; if (result != 0) { // We were unable to represent this number as a bitwise or of valid flags @@ -213,7 +215,7 @@ private static string InternalFlagsFormat(EnumInfo entry, ulong result) public static EnumInfo GetEnumValuesAndNames(Type enumType) { - return ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, null)); + return ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, null)); } private static ulong ToUInt64(object value) @@ -249,7 +251,7 @@ private static ulong ToUInt64(object value) } } - public static object ParseEnum(Type enumType, NamingStrategy namingStrategy, string value, bool disallowNumber) + public static object ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber) { ValidationUtils.ArgumentNotNull(enumType, nameof(enumType)); ValidationUtils.ArgumentNotNull(value, nameof(value)); @@ -259,7 +261,7 @@ public static object ParseEnum(Type enumType, NamingStrategy namingStrategy, str throw new ArgumentException("Type provided must be an Enum.", nameof(enumType)); } - EnumInfo entry = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); + EnumInfo entry = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); string[] enumNames = entry.Names; string[] resolvedNames = entry.ResolvedNames; ulong[] enumValues = entry.Values; @@ -292,7 +294,7 @@ public static object ParseEnum(Type enumType, NamingStrategy namingStrategy, str Type underlyingType = Enum.GetUnderlyingType(enumType); value = value.Trim(); - object temp = null; + object? temp = null; try { diff --git a/Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs index 6d6f8d7b0..53a97ecab 100644 --- a/Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs @@ -57,7 +57,7 @@ public override ObjectConstructor CreateParameterizedConstructor(MethodB return compiled; } - public override MethodCall CreateMethodCall(MethodBase method) + public override MethodCall CreateMethodCall(MethodBase method) { ValidationUtils.ArgumentNotNull(method, nameof(method)); @@ -70,7 +70,7 @@ public override MethodCall CreateMethodCall(MethodBase method) LambdaExpression lambdaExpression = Expression.Lambda(typeof(MethodCall), callExpression, targetParameterExpression, argsParameterExpression); - MethodCall compiled = (MethodCall)lambdaExpression.Compile(); + MethodCall compiled = (MethodCall)lambdaExpression.Compile(); return compiled; } @@ -79,9 +79,16 @@ private class ByRefParameter public Expression Value; public ParameterExpression Variable; public bool IsOut; + + public ByRefParameter(Expression value, ParameterExpression variable, bool isOut) + { + Value = value; + Variable = variable; + IsOut = isOut; + } } - private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression targetParameterExpression, ParameterExpression argsParameterExpression) + private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression? targetParameterExpression, ParameterExpression argsParameterExpression) { ParameterInfo[] parametersInfo = method.GetParameters(); @@ -117,7 +124,7 @@ private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpres if (isByRef) { ParameterExpression variable = Expression.Variable(parameterType); - refParameterMap.Add(new ByRefParameter {Value = argExpression, Variable = variable, IsOut = parameter.IsOut}); + refParameterMap.Add(new ByRefParameter(argExpression, variable, parameter.IsOut)); argExpression = variable; } @@ -137,7 +144,7 @@ private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpres } else { - Expression readParameter = EnsureCastExpression(targetParameterExpression, method.DeclaringType); + Expression readParameter = EnsureCastExpression(targetParameterExpression!, method.DeclaringType); callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression); } @@ -211,7 +218,7 @@ public override Func CreateDefaultConstructor(Type type) } } - public override Func CreateGet(PropertyInfo propertyInfo) + public override Func CreateGet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); @@ -221,7 +228,11 @@ public override Func CreateGet(PropertyInfo propertyInfo) ParameterExpression parameterExpression = Expression.Parameter(instanceType, "instance"); Expression resultExpression; - MethodInfo getMethod = propertyInfo.GetGetMethod(true); + MethodInfo? getMethod = propertyInfo.GetGetMethod(true); + if (getMethod == null) + { + throw new ArgumentException("Property does not have a getter."); + } if (getMethod.IsStatic) { @@ -238,11 +249,11 @@ public override Func CreateGet(PropertyInfo propertyInfo) LambdaExpression lambdaExpression = Expression.Lambda(typeof(Func), resultExpression, parameterExpression); - Func compiled = (Func)lambdaExpression.Compile(); + Func compiled = (Func)lambdaExpression.Compile(); return compiled; } - public override Func CreateGet(FieldInfo fieldInfo) + public override Func CreateGet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); @@ -262,11 +273,11 @@ public override Func CreateGet(FieldInfo fieldInfo) fieldExpression = EnsureCastExpression(fieldExpression, typeof(object)); - Func compiled = Expression.Lambda>(fieldExpression, sourceParameter).Compile(); + Func compiled = Expression.Lambda>(fieldExpression, sourceParameter).Compile(); return compiled; } - public override Action CreateSet(FieldInfo fieldInfo) + public override Action CreateSet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); @@ -298,11 +309,11 @@ public override Action CreateSet(FieldInfo fieldInfo) LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action), assignExpression, sourceParameterExpression, valueParameterExpression); - Action compiled = (Action)lambdaExpression.Compile(); + Action compiled = (Action)lambdaExpression.Compile(); return compiled; } - public override Action CreateSet(PropertyInfo propertyInfo) + public override Action CreateSet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); @@ -321,7 +332,11 @@ public override Action CreateSet(PropertyInfo propertyInfo) ParameterExpression valueParameter = Expression.Parameter(valueType, "value"); Expression readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType); - MethodInfo setMethod = propertyInfo.GetSetMethod(true); + MethodInfo? setMethod = propertyInfo.GetSetMethod(true); + if (setMethod == null) + { + throw new ArgumentException("Property does not have a setter."); + } Expression setExpression; if (setMethod.IsStatic) @@ -335,9 +350,9 @@ public override Action CreateSet(PropertyInfo propertyInfo) setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter); } - LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action), setExpression, instanceParameter, valueParameter); + LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action), setExpression, instanceParameter, valueParameter); - Action compiled = (Action)lambdaExpression.Compile(); + Action compiled = (Action)lambdaExpression.Compile(); return compiled; } diff --git a/Src/Newtonsoft.Json/Utilities/FSharpUtils.cs b/Src/Newtonsoft.Json/Utilities/FSharpUtils.cs index 55e15d814..38fe44886 100644 --- a/Src/Newtonsoft.Json/Utilities/FSharpUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/FSharpUtils.cs @@ -36,10 +36,10 @@ namespace Newtonsoft.Json.Utilities { internal class FSharpFunction { - private readonly object _instance; - private readonly MethodCall _invoker; + private readonly object? _instance; + private readonly MethodCall _invoker; - public FSharpFunction(object instance, MethodCall invoker) + public FSharpFunction(object? instance, MethodCall invoker) { _instance = instance; _invoker = invoker; @@ -62,15 +62,15 @@ internal static class FSharpUtils private static Type _mapType; public static Assembly FSharpCoreAssembly { get; private set; } - public static MethodCall IsUnion { get; private set; } - public static MethodCall GetUnionCases { get; private set; } - public static MethodCall PreComputeUnionTagReader { get; private set; } - public static MethodCall PreComputeUnionReader { get; private set; } - public static MethodCall PreComputeUnionConstructor { get; private set; } + public static MethodCall IsUnion { get; private set; } + public static MethodCall GetUnionCases { get; private set; } + public static MethodCall PreComputeUnionTagReader { get; private set; } + public static MethodCall PreComputeUnionReader { get; private set; } + public static MethodCall PreComputeUnionConstructor { get; private set; } public static Func GetUnionCaseInfoDeclaringType { get; private set; } public static Func GetUnionCaseInfoName { get; private set; } public static Func GetUnionCaseInfoTag { get; private set; } - public static MethodCall GetUnionCaseInfoFields { get; private set; } + public static MethodCall GetUnionCaseInfoFields { get; private set; } public const string FSharpSetTypeName = "FSharpSet`1"; public const string FSharpListTypeName = "FSharpList`1"; @@ -89,10 +89,10 @@ public static void EnsureInitialized(Assembly fsharpCoreAssembly) Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType"); MethodInfo isUnionMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "IsUnion", BindingFlags.Public | BindingFlags.Static); - IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(isUnionMethodInfo); + IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(isUnionMethodInfo)!; MethodInfo getUnionCasesMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "GetUnionCases", BindingFlags.Public | BindingFlags.Static); - GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getUnionCasesMethodInfo); + GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getUnionCasesMethodInfo)!; Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue"); @@ -102,9 +102,9 @@ public static void EnsureInitialized(Assembly fsharpCoreAssembly) Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo"); - GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Name")); - GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Tag")); - GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("DeclaringType")); + GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Name")!)!; + GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Tag")!)!; + GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("DeclaringType")!)!; GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(unionCaseInfo.GetMethod("GetFields")); Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule"); @@ -134,20 +134,20 @@ private static MethodInfo GetMethodWithNonPublicFallback(Type type, string metho methodInfo = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic); } - return methodInfo; + return methodInfo!; } - private static MethodCall CreateFSharpFuncCall(Type type, string methodName) + private static MethodCall CreateFSharpFuncCall(Type type, string methodName) { MethodInfo innerMethodInfo = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Public | BindingFlags.Static); MethodInfo invokeFunc = innerMethodInfo.ReturnType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance); - MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(innerMethodInfo); - MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(invokeFunc); + MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(innerMethodInfo); + MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(invokeFunc)!; - MethodCall createFunction = (target, args) => + MethodCall createFunction = (target, args) => { - object result = call(target, args); + object? result = call(target, args); FSharpFunction f = new FSharpFunction(result, invoke); return f; @@ -181,7 +181,7 @@ public static ObjectConstructor BuildMapCreator() ObjectConstructor creator = args => { // convert dictionary KeyValuePairs to Tuples - IEnumerable> values = (IEnumerable>)args[0]; + IEnumerable> values = (IEnumerable>)args[0]!; IEnumerable> tupleValues = values.Select(kv => new Tuple(kv.Key, kv.Value)); return ctorDelegate(tupleValues); diff --git a/Src/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs b/Src/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs index 5d60beb90..ab3b5522f 100644 --- a/Src/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs @@ -25,12 +25,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else using System.Linq; #endif using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using Newtonsoft.Json.Serialization; @@ -109,7 +111,7 @@ public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeNa new ImmutableCollectionTypeInfo(ImmutableDictionaryGenericTypeName, ImmutableDictionaryGenericTypeName, ImmutableDictionaryTypeName) }; - internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, out Type createdType, out ObjectConstructor parameterizedCreator) + internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, [NotNullWhen(true)]out Type? createdType, [NotNullWhen(true)]out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { @@ -141,7 +143,7 @@ internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type return false; } - internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, out Type createdType, out ObjectConstructor parameterizedCreator) + internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, [NotNullWhen(true)]out Type? createdType, [NotNullWhen(true)]out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { diff --git a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs index 0e6ffc28f..80fb1b65f 100644 --- a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs @@ -31,6 +31,8 @@ #endif using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -41,7 +43,7 @@ namespace Newtonsoft.Json.Utilities { internal static class BufferUtils { - public static char[] RentBuffer(IArrayPool bufferPool, int minSize) + public static char[] RentBuffer(IArrayPool? bufferPool, int minSize) { if (bufferPool == null) { @@ -52,12 +54,12 @@ public static char[] RentBuffer(IArrayPool bufferPool, int minSize) return buffer; } - public static void ReturnBuffer(IArrayPool bufferPool, char[] buffer) + public static void ReturnBuffer(IArrayPool? bufferPool, char[]? buffer) { bufferPool?.Return(buffer); } - public static char[] EnsureBufferSize(IArrayPool bufferPool, int size, char[] buffer) + public static char[] EnsureBufferSize(IArrayPool? bufferPool, int size, char[]? buffer) { if (bufferPool == null) { @@ -123,15 +125,16 @@ public static bool[] GetCharEscapeFlags(StringEscapeHandling stringEscapeHandlin return SingleQuoteCharEscapeFlags; } - public static bool ShouldEscapeJavaScriptString(string s, bool[] charEscapeFlags) + public static bool ShouldEscapeJavaScriptString(string? s, bool[] charEscapeFlags) { if (s == null) { return false; } - foreach (char c in s) + for (int i = 0; i < s.Length; i++) { + char c = s[i]; if (c >= charEscapeFlags.Length || charEscapeFlags[c]) { return true; @@ -141,8 +144,8 @@ public static bool ShouldEscapeJavaScriptString(string s, bool[] charEscapeFlags return false; } - public static void WriteEscapedJavaScriptString(TextWriter writer, string s, char delimiter, bool appendDelimiters, - bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool bufferPool, ref char[] writeBuffer) + public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, char delimiter, bool appendDelimiters, + bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool? bufferPool, ref char[]? writeBuffer) { // leading delimiter if (appendDelimiters) @@ -181,7 +184,7 @@ public static void WriteEscapedJavaScriptString(TextWriter writer, string s, cha continue; } - string escapedValue; + string? escapedValue; switch (c) { @@ -230,7 +233,7 @@ public static void WriteEscapedJavaScriptString(TextWriter writer, string s, cha writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, UnicodeTextLength, writeBuffer); } - StringUtils.ToCharAsUnicode(c, writeBuffer); + StringUtils.ToCharAsUnicode(c, writeBuffer!); // slightly hacky but it saves multiple conditions in if test escapedValue = EscapedUnicodeText; @@ -314,13 +317,13 @@ public static void WriteEscapedJavaScriptString(TextWriter writer, string s, cha } } - public static string ToEscapedJavaScriptString(string value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling) + public static string ToEscapedJavaScriptString(string? value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling) { bool[] charEscapeFlags = GetCharEscapeFlags(stringEscapeHandling, delimiter); using (StringWriter w = StringUtils.CreateStringWriter(value?.Length ?? 16)) { - char[] buffer = null; + char[]? buffer = null; WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters, charEscapeFlags, stringEscapeHandling, null, ref buffer); return w.ToString(); } @@ -450,7 +453,7 @@ private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimiter int length; bool isEscapedUnicodeText = false; - string escapedValue = null; + string? escapedValue = null; for (int i = lastWritePosition; i < s.Length; i++) { @@ -539,7 +542,7 @@ private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimiter lastWritePosition = i + 1; if (!isEscapedUnicodeText) { - await writer.WriteAsync(escapedValue, cancellationToken).ConfigureAwait(false); + await writer.WriteAsync(escapedValue!, cancellationToken).ConfigureAwait(false); } else { @@ -565,7 +568,7 @@ private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimiter } #endif - public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, out string errorMessage) + public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, [NotNullWhen(false)]out string? errorMessage) { dateTime = default; errorMessage = null; @@ -626,7 +629,7 @@ public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime return true; } - private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, out string errorMessage) + private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, out string? errorMessage) { integer = null; errorMessage = null; @@ -646,7 +649,7 @@ private static bool TryGetDateConstructorValue(JsonReader reader, out long? inte return false; } - integer = (long)reader.Value; + integer = (long)reader.Value!; return true; } } diff --git a/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs index 2150e4a3f..277f1ebb6 100644 --- a/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs @@ -53,7 +53,7 @@ public override ObjectConstructor CreateParameterizedConstructor(MethodB return a => method.Invoke(null, a); } - public override MethodCall CreateMethodCall(MethodBase method) + public override MethodCall CreateMethodCall(MethodBase method) { ValidationUtils.ArgumentNotNull(method, nameof(method)); @@ -79,28 +79,28 @@ public override Func CreateDefaultConstructor(Type type) return () => (T)constructorInfo.Invoke(null); } - public override Func CreateGet(PropertyInfo propertyInfo) + public override Func CreateGet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); return o => propertyInfo.GetValue(o, null); } - public override Func CreateGet(FieldInfo fieldInfo) + public override Func CreateGet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); return o => fieldInfo.GetValue(o); } - public override Action CreateSet(FieldInfo fieldInfo) + public override Action CreateSet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo)); return (o, v) => fieldInfo.SetValue(o, v); } - public override Action CreateSet(PropertyInfo propertyInfo) + public override Action CreateSet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); diff --git a/Src/Newtonsoft.Json/Utilities/LinqBridge.cs b/Src/Newtonsoft.Json/Utilities/LinqBridge.cs index dc8125838..fe93b82c0 100644 --- a/Src/Newtonsoft.Json/Utilities/LinqBridge.cs +++ b/Src/Newtonsoft.Json/Utilities/LinqBridge.cs @@ -35,6 +35,8 @@ using System.Globalization; using Newtonsoft.Json.Serialization; +#nullable disable + namespace Newtonsoft.Json.Utilities.LinqBridge { /// diff --git a/Src/Newtonsoft.Json/Utilities/MethodBinder.cs b/Src/Newtonsoft.Json/Utilities/MethodBinder.cs index 17d5c6278..541cfe5d5 100644 --- a/Src/Newtonsoft.Json/Utilities/MethodBinder.cs +++ b/Src/Newtonsoft.Json/Utilities/MethodBinder.cs @@ -126,7 +126,7 @@ private static bool FilterParameters(ParameterInfo[] parameters, IList typ } // check if the last parameter is ParamArray - Type paramArrayType = null; + Type? paramArrayType = null; if (enableParamArray) { @@ -211,7 +211,7 @@ public int Compare(ParameterInfo[] parameters1, ParameterInfo[] parameters2) return 1; } - Type paramArrayType1 = null, paramArrayType2 = null; + Type? paramArrayType1 = null, paramArrayType2 = null; if (_enableParamArray) { diff --git a/Src/Newtonsoft.Json/Utilities/MethodCall.cs b/Src/Newtonsoft.Json/Utilities/MethodCall.cs index 8b16e28f9..745a20712 100644 --- a/Src/Newtonsoft.Json/Utilities/MethodCall.cs +++ b/Src/Newtonsoft.Json/Utilities/MethodCall.cs @@ -25,5 +25,5 @@ namespace Newtonsoft.Json.Utilities { - internal delegate TResult MethodCall(T target, params object[] args); + internal delegate TResult MethodCall(T target, params object?[] args); } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs index 399e500d9..70a1583bb 100644 --- a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs @@ -38,7 +38,7 @@ namespace Newtonsoft.Json.Utilities internal static class MiscellaneousUtils { - public static bool ValueEquals(object objA, object objB) + public static bool ValueEquals(object? objA, object? objB) { if (objA == objB) { @@ -77,14 +77,14 @@ public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(stri return new ArgumentOutOfRangeException(paramName, newMessage); } - public static string ToString(object value) + public static string ToString(object? value) { if (value == null) { return "{null}"; } - return (value is string s) ? @"""" + s + @"""" : value.ToString(); + return (value is string s) ? @"""" + s + @"""" : value!.ToString(); } public static int ByteArrayCompare(byte[] a1, byte[] a2) @@ -107,9 +107,9 @@ public static int ByteArrayCompare(byte[] a1, byte[] a2) return 0; } - public static string GetPrefix(string qualifiedName) + public static string? GetPrefix(string qualifiedName) { - GetQualifiedNameParts(qualifiedName, out string prefix, out _); + GetQualifiedNameParts(qualifiedName, out string? prefix, out _); return prefix; } @@ -121,7 +121,7 @@ public static string GetLocalName(string qualifiedName) return localName; } - public static void GetQualifiedNameParts(string qualifiedName, out string prefix, out string localName) + public static void GetQualifiedNameParts(string qualifiedName, out string? prefix, out string localName) { int colonPosition = qualifiedName.IndexOf(':'); @@ -140,9 +140,10 @@ public static void GetQualifiedNameParts(string qualifiedName, out string prefix internal static RegexOptions GetRegexOptions(string optionsText) { RegexOptions options = RegexOptions.None; - foreach (char c in optionsText) + + for (int i = 0; i < optionsText.Length; i++) { - switch (c) + switch (optionsText[i]) { case 'i': options |= RegexOptions.IgnoreCase; diff --git a/Src/Newtonsoft.Json/Utilities/NullableAttributes.cs b/Src/Newtonsoft.Json/Utilities/NullableAttributes.cs new file mode 100644 index 000000000..ce153f2cf --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/NullableAttributes.cs @@ -0,0 +1,55 @@ +#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 System.Diagnostics.CodeAnalysis +{ + /// Specifies that an output will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true)] + internal sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute + { } + + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute + { } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs b/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs index 13d38f636..6b2d4ee24 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs @@ -36,7 +36,7 @@ namespace Newtonsoft.Json.Utilities { internal abstract class ReflectionDelegateFactory { - public Func CreateGet(MemberInfo memberInfo) + public Func CreateGet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { @@ -57,7 +57,7 @@ public Func CreateGet(MemberInfo memberInfo) throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } - public Action CreateSet(MemberInfo memberInfo) + public Action CreateSet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { @@ -72,12 +72,12 @@ public Action CreateSet(MemberInfo memberInfo) throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } - public abstract MethodCall CreateMethodCall(MethodBase method); + public abstract MethodCall CreateMethodCall(MethodBase method); public abstract ObjectConstructor CreateParameterizedConstructor(MethodBase method); public abstract Func CreateDefaultConstructor(Type type); - public abstract Func CreateGet(PropertyInfo propertyInfo); - public abstract Func CreateGet(FieldInfo fieldInfo); - public abstract Action CreateSet(FieldInfo fieldInfo); - public abstract Action CreateSet(PropertyInfo propertyInfo); + public abstract Func CreateGet(PropertyInfo propertyInfo); + public abstract Func CreateGet(FieldInfo fieldInfo); + public abstract Action CreateSet(FieldInfo fieldInfo); + public abstract Action CreateSet(PropertyInfo propertyInfo); } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs b/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs index 5eda2da0c..1463416db 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs @@ -39,37 +39,37 @@ namespace Newtonsoft.Json.Utilities { internal class ReflectionMember { - public Type MemberType { get; set; } - public Func Getter { get; set; } - public Action Setter { get; set; } + public Type? MemberType { get; set; } + public Func? Getter { get; set; } + public Action? Setter { get; set; } } internal class ReflectionObject { - public ObjectConstructor Creator { get; } + public ObjectConstructor? Creator { get; } public IDictionary Members { get; } - private ReflectionObject(ObjectConstructor creator) + private ReflectionObject(ObjectConstructor? creator) { Members = new Dictionary(); Creator = creator; } - public object GetValue(object target, string member) + public object? GetValue(object target, string member) { - Func getter = Members[member].Getter; + Func getter = Members[member].Getter!; return getter(target); } - public void SetValue(object target, string member, object value) + public void SetValue(object target, string member, object? value) { - Action setter = Members[member].Setter; + Action setter = Members[member].Setter!; setter(target, value); } public Type GetType(string member) { - return Members[member].MemberType; + return Members[member].MemberType!; } public static ReflectionObject Create(Type t, params string[] memberNames) @@ -77,11 +77,11 @@ public static ReflectionObject Create(Type t, params string[] memberNames) return Create(t, null, memberNames); } - public static ReflectionObject Create(Type t, MethodBase creator, params string[] memberNames) + public static ReflectionObject Create(Type t, MethodBase? creator, params string[] memberNames) { ReflectionDelegateFactory delegateFactory = JsonTypeReflector.ReflectionDelegateFactory; - ObjectConstructor creatorConstructor = null; + ObjectConstructor? creatorConstructor = null; if (creator != null) { creatorConstructor = delegateFactory.CreateParameterizedConstructor(creator); @@ -131,12 +131,12 @@ public static ReflectionObject Create(Type t, MethodBase creator, params string[ ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 0 && method.ReturnType != typeof(void)) { - MethodCall call = delegateFactory.CreateMethodCall(method); + MethodCall call = delegateFactory.CreateMethodCall(method); reflectionMember.Getter = target => call(target); } else if (parameters.Length == 1 && method.ReturnType == typeof(void)) { - MethodCall call = delegateFactory.CreateMethodCall(method); + MethodCall call = delegateFactory.CreateMethodCall(method); reflectionMember.Setter = (target, arg) => call(target, arg); } } diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index c4ed506e5..5e09de1e7 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -32,6 +32,8 @@ using System.Collections; using System.Globalization; using System.Text; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -96,7 +98,7 @@ public static bool IsVirtual(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - MethodInfo m = propertyInfo.GetGetMethod(true); + MethodInfo? m = propertyInfo.GetGetMethod(true); if (m != null && m.IsVirtual) { return true; @@ -111,11 +113,11 @@ public static bool IsVirtual(this PropertyInfo propertyInfo) return false; } - public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo) + public static MethodInfo? GetBaseDefinition(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); - MethodInfo m = propertyInfo.GetGetMethod(true); + MethodInfo? m = propertyInfo.GetGetMethod(true); if (m != null) { return m.GetBaseDefinition(); @@ -126,11 +128,13 @@ public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo) public static bool IsPublic(PropertyInfo property) { - if (property.GetGetMethod() != null && property.GetGetMethod().IsPublic) + var getMethod = property.GetGetMethod(); + if (getMethod != null && getMethod.IsPublic) { return true; } - if (property.GetSetMethod() != null && property.GetSetMethod().IsPublic) + var setMethod = property.GetSetMethod(); + if (setMethod != null && setMethod.IsPublic) { return true; } @@ -138,12 +142,12 @@ public static bool IsPublic(PropertyInfo property) return false; } - public static Type GetObjectType(object v) + public static Type? GetObjectType(object? v) { return v?.GetType(); } - public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, ISerializationBinder binder) + public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, ISerializationBinder? binder) { string fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder); @@ -158,11 +162,11 @@ public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assembly } } - private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder binder) + private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder? binder) { if (binder != null) { - binder.BindToName(t, out string assemblyName, out string typeName); + binder.BindToName(t, out string? assemblyName, out string? typeName); #if (NET20 || NET35) // for older SerializationBinder implementations that didn't have BindToName if (assemblyName == null & typeName == null) @@ -294,7 +298,7 @@ public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceD return ImplementsGenericDefinition(type, genericInterfaceDefinition, out _); } - public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType) + public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, [NotNullWhen(true)]out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, nameof(type)); ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, nameof(genericInterfaceDefinition)); @@ -341,7 +345,7 @@ public static bool InheritsGenericDefinition(Type type, Type genericClassDefinit return InheritsGenericDefinition(type, genericClassDefinition, out _); } - public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType) + public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, nameof(type)); ValidationUtils.ArgumentNotNull(genericClassDefinition, nameof(genericClassDefinition)); @@ -354,7 +358,7 @@ public static bool InheritsGenericDefinition(Type type, Type genericClassDefinit return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType); } - private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType) + private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type? implementingType) { do { @@ -377,7 +381,7 @@ private static bool InheritsGenericDefinitionInternal(Type currentType, Type gen /// /// The type. /// The type of the typed collection's items. - public static Type GetCollectionItemType(Type type) + public static Type? GetCollectionItemType(Type type) { ValidationUtils.ArgumentNotNull(type, nameof(type)); @@ -385,14 +389,14 @@ public static Type GetCollectionItemType(Type type) { return type.GetElementType(); } - if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type genericListType)) + if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type? genericListType)) { - if (genericListType.IsGenericTypeDefinition()) + if (genericListType!.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } - return genericListType.GetGenericArguments()[0]; + return genericListType!.GetGenericArguments()[0]; } if (typeof(IEnumerable).IsAssignableFrom(type)) { @@ -402,18 +406,18 @@ public static Type GetCollectionItemType(Type type) throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } - public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType) + public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type? keyType, out Type? valueType) { ValidationUtils.ArgumentNotNull(dictionaryType, nameof(dictionaryType)); - if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out Type genericDictionaryType)) + if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out Type? genericDictionaryType)) { - if (genericDictionaryType.IsGenericTypeDefinition()) + if (genericDictionaryType!.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); } - Type[] dictionaryGenericArguments = genericDictionaryType.GetGenericArguments(); + Type[] dictionaryGenericArguments = genericDictionaryType!.GetGenericArguments(); keyType = dictionaryGenericArguments[0]; valueType = dictionaryGenericArguments[1]; @@ -522,7 +526,7 @@ public static object GetMemberValue(MemberInfo member, object target) /// The member. /// The target. /// The value. - public static void SetMemberValue(MemberInfo member, object target, object value) + public static void SetMemberValue(MemberInfo member, object target, object? value) { ValidationUtils.ArgumentNotNull(member, nameof(member)); ValidationUtils.ArgumentNotNull(target, nameof(target)); @@ -721,12 +725,12 @@ private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags return true; } - public static T GetAttribute(object attributeProvider) where T : Attribute + public static T? GetAttribute(object attributeProvider) where T : Attribute { return GetAttribute(attributeProvider, true); } - public static T GetAttribute(object attributeProvider, bool inherit) where T : Attribute + public static T? GetAttribute(object attributeProvider, bool inherit) where T : Attribute { T[] attributes = GetAttributes(attributeProvider, inherit); @@ -746,7 +750,7 @@ public static T[] GetAttributes(object attributeProvider, bool inherit) where return a.Cast().ToArray(); } - public static Attribute[] GetAttributes(object attributeProvider, Type attributeType, bool inherit) + public static Attribute[] GetAttributes(object attributeProvider, Type? attributeType, bool inherit) { ValidationUtils.ArgumentNotNull(attributeProvider, nameof(attributeProvider)); @@ -797,7 +801,7 @@ public static T[] GetAttributes(object attributeProvider, bool inherit) where return GetAttributes(attributeProvider, typeof(T), inherit).Cast().ToArray(); } - public static Attribute[] GetAttributes(object provider, Type attributeType, bool inherit) + public static Attribute[] GetAttributes(object provider, Type? attributeType, bool inherit) { switch (provider) { @@ -819,12 +823,12 @@ public static Attribute[] GetAttributes(object provider, Type attributeType, boo } #endif - public static StructMultiKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName) + public static StructMultiKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName) { int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName); string typeName; - string assemblyName; + string? assemblyName; if (assemblyDelimiterIndex != null) { @@ -837,7 +841,7 @@ public static StructMultiKey SplitFullyQualifiedTypeName(string assemblyName = null; } - return new StructMultiKey(assemblyName, typeName); + return new StructMultiKey(assemblyName, typeName); } private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName) @@ -1038,7 +1042,7 @@ public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType return isMethodOverriden; } - public static object GetDefaultValue(Type type) + public static object? GetDefaultValue(Type type) { if (!type.IsValueType()) { @@ -1089,4 +1093,4 @@ public static object GetDefaultValue(Type type) return Activator.CreateInstance(type); } } -} +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/StringBuffer.cs b/Src/Newtonsoft.Json/Utilities/StringBuffer.cs index 8c9dcf47d..13f4f8666 100644 --- a/Src/Newtonsoft.Json/Utilities/StringBuffer.cs +++ b/Src/Newtonsoft.Json/Utilities/StringBuffer.cs @@ -32,7 +32,7 @@ namespace Newtonsoft.Json.Utilities /// internal struct StringBuffer { - private char[] _buffer; + private char[]? _buffer; private int _position; public int Position @@ -43,7 +43,7 @@ public int Position public bool IsEmpty => _buffer == null; - public StringBuffer(IArrayPool bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize)) + public StringBuffer(IArrayPool? bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize)) { } @@ -53,21 +53,21 @@ private StringBuffer(char[] buffer) _position = 0; } - public void Append(IArrayPool bufferPool, char value) + public void Append(IArrayPool? bufferPool, char value) { // test if the buffer array is large enough to take the value - if (_position == _buffer.Length) + if (_position == _buffer!.Length) { EnsureSize(bufferPool, 1); } // set value and increment poisition - _buffer[_position++] = value; + _buffer![_position++] = value; } - public void Append(IArrayPool bufferPool, char[] buffer, int startIndex, int count) + public void Append(IArrayPool? bufferPool, char[] buffer, int startIndex, int count) { - if (_position + count >= _buffer.Length) + if (_position + count >= _buffer!.Length) { EnsureSize(bufferPool, count); } @@ -77,7 +77,7 @@ public void Append(IArrayPool bufferPool, char[] buffer, int startIndex, i _position += count; } - public void Clear(IArrayPool bufferPool) + public void Clear(IArrayPool? bufferPool) { if (_buffer != null) { @@ -87,7 +87,7 @@ public void Clear(IArrayPool bufferPool) _position = 0; } - private void EnsureSize(IArrayPool bufferPool, int appendLength) + private void EnsureSize(IArrayPool? bufferPool, int appendLength) { char[] newBuffer = BufferUtils.RentBuffer(bufferPool, (_position + appendLength) * 2); @@ -111,6 +111,6 @@ public string ToString(int start, int length) return new string(_buffer, start, length); } - public char[] InternalBuffer => _buffer; + public char[]? InternalBuffer => _buffer; } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/StringUtils.cs b/Src/Newtonsoft.Json/Utilities/StringUtils.cs index 049c70a74..8544a3f59 100644 --- a/Src/Newtonsoft.Json/Utilities/StringUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/StringUtils.cs @@ -45,27 +45,27 @@ internal static class StringUtils public const char LineFeed = '\n'; public const char Tab = '\t'; - public static string FormatWith(this string format, IFormatProvider provider, object arg0) + public static string FormatWith(this string format, IFormatProvider provider, object? arg0) { - return format.FormatWith(provider, new[] { arg0 }); + return format.FormatWith(provider, new object?[] { arg0 }); } - public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1) + public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1) { - return format.FormatWith(provider, new[] { arg0, arg1 }); + return format.FormatWith(provider, new object?[] { arg0, arg1 }); } - public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1, object arg2) + public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2) { - return format.FormatWith(provider, new[] { arg0, arg1, arg2 }); + return format.FormatWith(provider, new object?[] { arg0, arg1, arg2 }); } - public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1, object arg2, object arg3) + public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2, object? arg3) { - return format.FormatWith(provider, new[] { arg0, arg1, arg2, arg3 }); + return format.FormatWith(provider, new object?[] { arg0, arg1, arg2, arg3 }); } - private static string FormatWith(this string format, IFormatProvider provider, params object[] args) + private static string FormatWith(this string format, IFormatProvider provider, params object?[] args) { // leave this a private to force code to use an explicit overload // avoids stack memory being reserved for the object array diff --git a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs index 646080814..77b756915 100644 --- a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs +++ b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs @@ -26,6 +26,8 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; #if !HAVE_LINQ using Newtonsoft.Json.Utilities.LinqBridge; #else @@ -40,12 +42,12 @@ internal static class TypeExtensions #if !DOTNET private static readonly BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; - public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo) + public static MethodInfo? GetGetMethod(this PropertyInfo propertyInfo) { return propertyInfo.GetGetMethod(false); } - public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic) + public static MethodInfo? GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic) { MethodInfo getMethod = propertyInfo.GetMethod; if (getMethod != null && (getMethod.IsPublic || nonPublic)) @@ -56,12 +58,12 @@ public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPu return null; } - public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo) + public static MethodInfo? GetSetMethod(this PropertyInfo propertyInfo) { return propertyInfo.GetSetMethod(false); } - public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic) + public static MethodInfo? GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic) { MethodInfo setMethod = propertyInfo.SetMethod; if (setMethod != null && (setMethod.IsPublic || nonPublic)) @@ -85,7 +87,7 @@ public static bool IsAssignableFrom(this Type type, Type c) } #endif - public static bool IsInstanceOfType(this Type type, object o) + public static bool IsInstanceOfType(this Type type, object? o) { if (o == null) { @@ -215,7 +217,7 @@ public static bool IsSealed(this Type type) } #if (PORTABLE40 || DOTNET || PORTABLE) - public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object placeholder1, Type propertyType, IList indexParameters, object placeholder2) + public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object? placeholder1, Type propertyType, IList indexParameters, object? placeholder2) { IEnumerable propertyInfos = type.GetProperties(bindingFlags); @@ -289,12 +291,12 @@ public static MethodInfo GetMethod(this Type type, IList parameterTypes) return type.GetMethod(null, parameterTypes); } - public static MethodInfo GetMethod(this Type type, string name, IList parameterTypes) + public static MethodInfo GetMethod(this Type type, string? name, IList parameterTypes) { return type.GetMethod(name, DefaultFlags, null, parameterTypes, null); } - public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags, object placeHolder1, IList parameterTypes, object placeHolder2) + public static MethodInfo GetMethod(this Type type, string? name, BindingFlags bindingFlags, object? placeHolder1, IList parameterTypes, object? placeHolder2) { return MethodBinder.SelectMethod(type.GetTypeInfo().DeclaredMethods.Where(m => (name == null || m.Name == name) && TestAccessibility(m, bindingFlags)), parameterTypes); } @@ -314,7 +316,7 @@ public static ConstructorInfo GetConstructor(this Type type, IList paramet return type.GetConstructor(DefaultFlags, null, parameterTypes, null); } - public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object placeholder1, IList parameterTypes, object placeholder2) + public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object? placeholder1, IList parameterTypes, object? placeholder2) { return MethodBinder.SelectMethod(type.GetConstructors(bindingFlags), parameterTypes); } @@ -338,12 +340,12 @@ public static MemberInfo[] GetMemberInternal(this Type type, string member, Memb TestAccessibility(m, bindingFlags)).ToArray(); } - public static FieldInfo GetField(this Type type, string member) + public static FieldInfo? GetField(this Type type, string member) { return type.GetField(member, DefaultFlags); } - public static FieldInfo GetField(this Type type, string member, BindingFlags bindingFlags) + public static FieldInfo? GetField(this Type type, string member, BindingFlags bindingFlags) { FieldInfo field = type.GetTypeInfo().GetDeclaredField(member); if (field == null || !TestAccessibility(field, bindingFlags)) @@ -378,7 +380,7 @@ private static bool ContainsMemberName(IEnumerable members, string n private static IList GetMembersRecursive(this TypeInfo type) { - TypeInfo t = type; + TypeInfo? t = type; List members = new List(); while (t != null) { @@ -397,7 +399,7 @@ private static IList GetMembersRecursive(this TypeInfo type) private static IList GetPropertiesRecursive(this TypeInfo type) { - TypeInfo t = type; + TypeInfo? t = type; List properties = new List(); while (t != null) { @@ -416,7 +418,7 @@ private static IList GetPropertiesRecursive(this TypeInfo type) private static IList GetFieldsRecursive(this TypeInfo type) { - TypeInfo t = type; + TypeInfo? t = type; List fields = new List(); while (t != null) { @@ -438,12 +440,12 @@ public static IEnumerable GetMethods(this Type type, BindingFlags bi return type.GetTypeInfo().DeclaredMethods; } - public static PropertyInfo GetProperty(this Type type, string name) + public static PropertyInfo? GetProperty(this Type type, string name) { return type.GetProperty(name, DefaultFlags); } - public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags) + public static PropertyInfo? GetProperty(this Type type, string name, BindingFlags bindingFlags) { PropertyInfo property = type.GetTypeInfo().GetDeclaredProperty(name); if (property == null || !TestAccessibility(property, bindingFlags)) @@ -576,7 +578,7 @@ public static bool IsPrimitive(this Type type) #endif } - public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, out Type match) + public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, [NotNullWhen(true)]out Type? match) { Type current = type; diff --git a/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs b/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs index 845ba3ea3..df17082f4 100644 --- a/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs @@ -24,12 +24,14 @@ #endregion using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; namespace Newtonsoft.Json.Utilities { internal static class ValidationUtils { - public static void ArgumentNotNull(object value, string parameterName) + public static void ArgumentNotNull([NotNull]object? value, string parameterName) { if (value == null) { diff --git a/Src/global.json b/Src/global.json index 2be3e8661..543cd3478 100644 --- a/Src/global.json +++ b/Src/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.2.105" + "version": "3.0.100-preview8-013317" } } \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 81a74e755..a48f95953 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -3,7 +3,7 @@ trigger: - release/* pool: - vmImage: 'VS2017-Win2016' + vmImage: 'windows-2019' steps: - powershell: |