diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index c960513e9ab3bc..c43f9c9a5f55cf 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -36,17 +36,18 @@ public JsonArray(System.Collections.Generic.IEnumerable values) { } public JsonArray(System.Collections.Generic.IEnumerable values) { } public int Count { get { throw null; } } public bool IsReadOnly { get { throw null; } } + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public System.Text.Json.JsonNode this[int idx] { get { throw null; } set { } } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } - public void Add(System.Text.Json.JsonNode value) { } + public void Add(System.Text.Json.JsonNode? value) { } public void Clear() { } public override System.Text.Json.JsonNode Clone() { throw null; } - public bool Contains(System.Text.Json.JsonNode value) { throw null; } + public bool Contains(System.Text.Json.JsonNode? value) { throw null; } public System.Text.Json.JsonArrayEnumerator GetEnumerator() { throw null; } - public int IndexOf(System.Text.Json.JsonNode item) { throw null; } - public void Insert(int index, System.Text.Json.JsonNode item) { } - public int LastIndexOf(System.Text.Json.JsonNode item) { throw null; } - public bool Remove(System.Text.Json.JsonNode item) { throw null; } + public int IndexOf(System.Text.Json.JsonNode? item) { throw null; } + public void Insert(int index, System.Text.Json.JsonNode? item) { } + public int LastIndexOf(System.Text.Json.JsonNode? item) { throw null; } + public bool Remove(System.Text.Json.JsonNode? item) { throw null; } public int RemoveAll(System.Predicate match) { throw null; } public void RemoveAt(int index) { } void System.Collections.Generic.ICollection.CopyTo(System.Text.Json.JsonNode[] array, int arrayIndex) { } @@ -71,11 +72,11 @@ public JsonBoolean(bool value) { } public bool Value { get { throw null; } set { } } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public override System.Text.Json.JsonNode Clone() { throw null; } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonBoolean other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Text.Json.JsonBoolean? other) { throw null; } public override int GetHashCode() { throw null; } - public static bool operator ==(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } - public static bool operator !=(System.Text.Json.JsonBoolean left, System.Text.Json.JsonBoolean right) { throw null; } + public static bool operator ==(System.Text.Json.JsonBoolean? left, System.Text.Json.JsonBoolean? right) { throw null; } + public static bool operator !=(System.Text.Json.JsonBoolean? left, System.Text.Json.JsonBoolean? right) { throw null; } public override string ToString() { throw null; } } public enum JsonCommentHandling : byte @@ -96,7 +97,7 @@ public void Dispose() { } public static System.Text.Json.JsonDocument Parse(string json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Threading.Tasks.Task ParseAsync(System.IO.Stream utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Text.Json.JsonDocument ParseValue(ref System.Text.Json.Utf8JsonReader reader) { throw null; } - public static bool TryParseValue(ref System.Text.Json.Utf8JsonReader reader, out System.Text.Json.JsonDocument document) { throw null; } + public static bool TryParseValue(ref System.Text.Json.Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonDocument? document) { throw null; } public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } } public partial struct JsonDocumentOptions @@ -135,16 +136,16 @@ public readonly partial struct JsonElement [System.CLSCompliantAttribute(false)] public sbyte GetSByte() { throw null; } public float GetSingle() { throw null; } - public string GetString() { throw null; } + public string? GetString() { throw null; } [System.CLSCompliantAttribute(false)] public ushort GetUInt16() { throw null; } [System.CLSCompliantAttribute(false)] public uint GetUInt32() { throw null; } [System.CLSCompliantAttribute(false)] public ulong GetUInt64() { throw null; } - public override string ToString() { throw null; } + public override string? ToString() { throw null; } public bool TryGetByte(out byte value) { throw null; } - public bool TryGetBytesFromBase64(out byte[] value) { throw null; } + public bool TryGetBytesFromBase64([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out byte[]? value) { throw null; } public bool TryGetDateTime(out System.DateTime value) { throw null; } public bool TryGetDateTimeOffset(out System.DateTimeOffset value) { throw null; } public bool TryGetDecimal(out decimal value) { throw null; } @@ -167,7 +168,7 @@ public readonly partial struct JsonElement public bool TryGetUInt64(out ulong value) { throw null; } public bool ValueEquals(System.ReadOnlySpan utf8Text) { throw null; } public bool ValueEquals(System.ReadOnlySpan text) { throw null; } - public bool ValueEquals(string text) { throw null; } + public bool ValueEquals(string? text) { throw null; } public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } public partial struct ArrayEnumerator : System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerator, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable { @@ -201,10 +202,10 @@ public void Reset() { } private readonly object _dummy; private readonly int _dummyPrimitive; public System.ReadOnlySpan EncodedUtf8Bytes { get { throw null; } } - public static System.Text.Json.JsonEncodedText Encode(System.ReadOnlySpan utf8Value, System.Text.Encodings.Web.JavaScriptEncoder encoder = null) { throw null; } - public static System.Text.Json.JsonEncodedText Encode(System.ReadOnlySpan value, System.Text.Encodings.Web.JavaScriptEncoder encoder = null) { throw null; } - public static System.Text.Json.JsonEncodedText Encode(string value, System.Text.Encodings.Web.JavaScriptEncoder encoder = null) { throw null; } - public override bool Equals(object obj) { throw null; } + public static System.Text.Json.JsonEncodedText Encode(System.ReadOnlySpan utf8Value, System.Text.Encodings.Web.JavaScriptEncoder? encoder = null) { throw null; } + public static System.Text.Json.JsonEncodedText Encode(System.ReadOnlySpan value, System.Text.Encodings.Web.JavaScriptEncoder? encoder = null) { throw null; } + public static System.Text.Json.JsonEncodedText Encode(string value, System.Text.Encodings.Web.JavaScriptEncoder? encoder = null) { throw null; } + public override bool Equals(object? obj) { throw null; } public bool Equals(System.Text.Json.JsonEncodedText other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } @@ -213,14 +214,14 @@ public partial class JsonException : System.Exception { public JsonException() { } protected JsonException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } - public JsonException(string message) { } - public JsonException(string message, System.Exception innerException) { } - public JsonException(string message, string path, long? lineNumber, long? bytePositionInLine) { } - public JsonException(string message, string path, long? lineNumber, long? bytePositionInLine, System.Exception innerException) { } + public JsonException(string? message) { } + public JsonException(string? message, System.Exception? innerException) { } + public JsonException(string? message, string path, long? lineNumber, long? bytePositionInLine) { } + public JsonException(string? message, string path, long? lineNumber, long? bytePositionInLine, System.Exception? innerException) { } public long? BytePositionInLine { get { throw null; } } public long? LineNumber { get { throw null; } } public override string Message { get { throw null; } } - public string Path { get { throw null; } } + public string? Path { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } public abstract partial class JsonNamingPolicy @@ -250,7 +251,7 @@ internal JsonNode() { } [System.CLSCompliantAttribute(false)] public static implicit operator System.Text.Json.JsonNode (sbyte value) { throw null; } public static implicit operator System.Text.Json.JsonNode (float value) { throw null; } - public static implicit operator System.Text.Json.JsonNode (string value) { throw null; } + public static implicit operator System.Text.Json.JsonNode (string? value) { throw null; } [System.CLSCompliantAttribute(false)] public static implicit operator System.Text.Json.JsonNode (ushort value) { throw null; } [System.CLSCompliantAttribute(false)] @@ -259,7 +260,7 @@ internal JsonNode() { } public static implicit operator System.Text.Json.JsonNode (ulong value) { throw null; } public static System.Text.Json.JsonNode Parse(string json, System.Text.Json.JsonNodeOptions options = default(System.Text.Json.JsonNodeOptions)) { throw null; } public string ToJsonString() { throw null; } - public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, out System.Text.Json.JsonNode jsonNode) { throw null; } + public static bool TryGetNode(System.Text.Json.JsonElement jsonElement, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonNode? jsonNode) { throw null; } public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } } public partial struct JsonNodeOptions @@ -275,11 +276,11 @@ public sealed partial class JsonNull : System.Text.Json.JsonNode, System.IEquata public JsonNull() { } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public override System.Text.Json.JsonNode Clone() { throw null; } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonNull other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Text.Json.JsonNull? other) { throw null; } public override int GetHashCode() { throw null; } - public static bool operator ==(System.Text.Json.JsonNull left, System.Text.Json.JsonNull right) { throw null; } - public static bool operator !=(System.Text.Json.JsonNull left, System.Text.Json.JsonNull right) { throw null; } + public static bool operator ==(System.Text.Json.JsonNull? left, System.Text.Json.JsonNull? right) { throw null; } + public static bool operator !=(System.Text.Json.JsonNull? left, System.Text.Json.JsonNull? right) { throw null; } public override string ToString() { throw null; } } public sealed partial class JsonNumber : System.Text.Json.JsonNode, System.IEquatable @@ -303,8 +304,8 @@ public JsonNumber(uint value) { } public JsonNumber(ulong value) { } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public override System.Text.Json.JsonNode Clone() { throw null; } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonNumber other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Text.Json.JsonNumber? other) { throw null; } public byte GetByte() { throw null; } public decimal GetDecimal() { throw null; } public double GetDouble() { throw null; } @@ -321,8 +322,8 @@ public JsonNumber(ulong value) { } public uint GetUInt32() { throw null; } [System.CLSCompliantAttribute(false)] public ulong GetUInt64() { throw null; } - public static bool operator ==(System.Text.Json.JsonNumber left, System.Text.Json.JsonNumber right) { throw null; } - public static bool operator !=(System.Text.Json.JsonNumber left, System.Text.Json.JsonNumber right) { throw null; } + public static bool operator ==(System.Text.Json.JsonNumber? left, System.Text.Json.JsonNumber? right) { throw null; } + public static bool operator !=(System.Text.Json.JsonNumber? left, System.Text.Json.JsonNumber? right) { throw null; } public void SetByte(byte value) { } public void SetDecimal(decimal value) { } public void SetDouble(double value) { } @@ -359,12 +360,13 @@ public void SetUInt64(ulong value) { } public sealed partial class JsonObject : System.Text.Json.JsonNode, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public JsonObject() { } - public JsonObject(System.Collections.Generic.IEnumerable> jsonProperties) { } + public JsonObject(System.Collections.Generic.IEnumerable> jsonProperties) { } + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public System.Text.Json.JsonNode this[string propertyName] { get { throw null; } set { } } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } - public void Add(System.Collections.Generic.KeyValuePair jsonProperty) { } - public void Add(string propertyName, System.Text.Json.JsonNode propertyValue) { } - public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } + public void Add(System.Collections.Generic.KeyValuePair jsonProperty) { } + public void Add(string propertyName, System.Text.Json.JsonNode? propertyValue) { } + public void AddRange(System.Collections.Generic.IEnumerable> jsonProperties) { } public override System.Text.Json.JsonNode Clone() { throw null; } public bool ContainsProperty(string propertyName) { throw null; } public bool ContainsProperty(string propertyName, System.StringComparison stringComparison) { throw null; } @@ -379,14 +381,14 @@ public void AddRange(System.Collections.Generic.IEnumerable GetPropertyValues() { throw null; } public bool Remove(string propertyName) { throw null; } public bool Remove(string propertyName, System.StringComparison stringComparison) { throw null; } - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - public bool TryGetJsonArrayPropertyValue(string propertyName, System.StringComparison stringComparison, out System.Text.Json.JsonArray jsonArray) { throw null; } - public bool TryGetJsonArrayPropertyValue(string propertyName, out System.Text.Json.JsonArray jsonArray) { throw null; } - public bool TryGetJsonObjectPropertyValue(string propertyName, System.StringComparison stringComparison, out System.Text.Json.JsonObject jsonObject) { throw null; } - public bool TryGetJsonObjectPropertyValue(string propertyName, out System.Text.Json.JsonObject jsonObject) { throw null; } - public bool TryGetPropertyValue(string propertyName, System.StringComparison stringComparison, out System.Text.Json.JsonNode jsonNode) { throw null; } - public bool TryGetPropertyValue(string propertyName, out System.Text.Json.JsonNode jsonNode) { throw null; } + public bool TryGetJsonArrayPropertyValue(string propertyName, System.StringComparison stringComparison, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonArray? jsonArray) { throw null; } + public bool TryGetJsonArrayPropertyValue(string propertyName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonArray? jsonArray) { throw null; } + public bool TryGetJsonObjectPropertyValue(string propertyName, System.StringComparison stringComparison, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonObject? jsonObject) { throw null; } + public bool TryGetJsonObjectPropertyValue(string propertyName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonObject? jsonObject) { throw null; } + public bool TryGetPropertyValue(string propertyName, System.StringComparison stringComparison, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonNode? jsonNode) { throw null; } + public bool TryGetPropertyValue(string propertyName, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonNode? jsonNode) { throw null; } } public partial struct JsonObjectEnumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { @@ -407,7 +409,7 @@ public readonly partial struct JsonProperty public System.Text.Json.JsonElement Value { get { throw null; } } public bool NameEquals(System.ReadOnlySpan utf8Text) { throw null; } public bool NameEquals(System.ReadOnlySpan text) { throw null; } - public bool NameEquals(string text) { throw null; } + public bool NameEquals(string? text) { throw null; } public override string ToString() { throw null; } public void WriteTo(System.Text.Json.Utf8JsonWriter writer) { } } @@ -427,22 +429,25 @@ public partial struct JsonReaderState } public static partial class JsonSerializer { - public static object Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static object Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static object Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static TValue Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static TValue Deserialize(string json, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static TValue Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static string Serialize(object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { } - public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, TValue value, System.Text.Json.JsonSerializerOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static byte[] SerializeToUtf8Bytes(object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } - public static void Serialize(System.Text.Json.Utf8JsonWriter writer, TValue value, System.Text.Json.JsonSerializerOptions options = null) { } - public static string Serialize(TValue value, System.Text.Json.JsonSerializerOptions options = null) { throw null; } + public static object? Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize(string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static string Serialize(object? value, System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object? value, System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object? value, System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static byte[] SerializeToUtf8Bytes(object? value, System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static void Serialize(System.Text.Json.Utf8JsonWriter writer, TValue value, System.Text.Json.JsonSerializerOptions? options = null) { } + public static string Serialize(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } } public sealed partial class JsonSerializerOptions { @@ -450,16 +455,16 @@ public JsonSerializerOptions() { } public bool AllowTrailingCommas { get { throw null; } set { } } public System.Collections.Generic.IList Converters { get { throw null; } } public int DefaultBufferSize { get { throw null; } set { } } - public System.Text.Json.JsonNamingPolicy DictionaryKeyPolicy { get { throw null; } set { } } - public System.Text.Encodings.Web.JavaScriptEncoder Encoder { get { throw null; } set { } } + public System.Text.Json.JsonNamingPolicy? DictionaryKeyPolicy { get { throw null; } set { } } + public System.Text.Encodings.Web.JavaScriptEncoder? Encoder { get { throw null; } set { } } public bool IgnoreNullValues { get { throw null; } set { } } public bool IgnoreReadOnlyProperties { get { throw null; } set { } } public int MaxDepth { get { throw null; } set { } } public bool PropertyNameCaseInsensitive { get { throw null; } set { } } - public System.Text.Json.JsonNamingPolicy PropertyNamingPolicy { get { throw null; } set { } } + public System.Text.Json.JsonNamingPolicy? PropertyNamingPolicy { get { throw null; } set { } } public System.Text.Json.JsonCommentHandling ReadCommentHandling { get { throw null; } set { } } public bool WriteIndented { get { throw null; } set { } } - public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } + public System.Text.Json.Serialization.JsonConverter? GetConverter(System.Type typeToConvert) { throw null; } } public sealed partial class JsonString : System.Text.Json.JsonNode, System.IEquatable { @@ -472,14 +477,14 @@ public JsonString(string value) { } public string Value { get { throw null; } set { } } public override System.Text.Json.JsonValueKind ValueKind { get { throw null; } } public override System.Text.Json.JsonNode Clone() { throw null; } - public override bool Equals(object obj) { throw null; } - public bool Equals(System.Text.Json.JsonString other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Text.Json.JsonString? other) { throw null; } public System.DateTime GetDateTime() { throw null; } public System.DateTimeOffset GetDateTimeOffset() { throw null; } public System.Guid GetGuid() { throw null; } public override int GetHashCode() { throw null; } - public static bool operator ==(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } - public static bool operator !=(System.Text.Json.JsonString left, System.Text.Json.JsonString right) { throw null; } + public static bool operator ==(System.Text.Json.JsonString? left, System.Text.Json.JsonString? right) { throw null; } + public static bool operator !=(System.Text.Json.JsonString? left, System.Text.Json.JsonString? right) { throw null; } public override string ToString() { throw null; } public bool TryGetDateTime(out System.DateTime value) { throw null; } public bool TryGetDateTimeOffset(out System.DateTimeOffset value) { throw null; } @@ -515,7 +520,7 @@ public partial struct JsonWriterOptions { private object _dummy; private int _dummyPrimitive; - public System.Text.Encodings.Web.JavaScriptEncoder Encoder { readonly get { throw null; } set { } } + public System.Text.Encodings.Web.JavaScriptEncoder? Encoder { readonly get { throw null; } set { } } public bool Indented { get { throw null; } set { } } public bool SkipValidation { get { throw null; } set { } } } @@ -552,7 +557,7 @@ public ref partial struct Utf8JsonReader [System.CLSCompliantAttribute(false)] public sbyte GetSByte() { throw null; } public float GetSingle() { throw null; } - public string GetString() { throw null; } + public string? GetString() { throw null; } [System.CLSCompliantAttribute(false)] public ushort GetUInt16() { throw null; } [System.CLSCompliantAttribute(false)] @@ -562,7 +567,7 @@ public ref partial struct Utf8JsonReader public bool Read() { throw null; } public void Skip() { } public bool TryGetByte(out byte value) { throw null; } - public bool TryGetBytesFromBase64(out byte[] value) { throw null; } + public bool TryGetBytesFromBase64([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out byte[]? value) { throw null; } public bool TryGetDateTime(out System.DateTime value) { throw null; } public bool TryGetDateTimeOffset(out System.DateTimeOffset value) { throw null; } public bool TryGetDecimal(out decimal value) { throw null; } @@ -583,7 +588,7 @@ public void Skip() { } public bool TrySkip() { throw null; } public bool ValueTextEquals(System.ReadOnlySpan utf8Text) { throw null; } public bool ValueTextEquals(System.ReadOnlySpan text) { throw null; } - public bool ValueTextEquals(string text) { throw null; } + public bool ValueTextEquals(string? text) { throw null; } } public sealed partial class Utf8JsonWriter : System.IAsyncDisposable, System.IDisposable { @@ -684,35 +689,35 @@ public void WriteString(System.ReadOnlySpan utf8PropertyName, System.DateT public void WriteString(System.ReadOnlySpan utf8PropertyName, System.Guid value) { } public void WriteString(System.ReadOnlySpan utf8PropertyName, System.ReadOnlySpan utf8Value) { } public void WriteString(System.ReadOnlySpan utf8PropertyName, System.ReadOnlySpan value) { } - public void WriteString(System.ReadOnlySpan utf8PropertyName, string value) { } + public void WriteString(System.ReadOnlySpan utf8PropertyName, string? value) { } public void WriteString(System.ReadOnlySpan utf8PropertyName, System.Text.Json.JsonEncodedText value) { } public void WriteString(System.ReadOnlySpan propertyName, System.DateTime value) { } public void WriteString(System.ReadOnlySpan propertyName, System.DateTimeOffset value) { } public void WriteString(System.ReadOnlySpan propertyName, System.Guid value) { } public void WriteString(System.ReadOnlySpan propertyName, System.ReadOnlySpan utf8Value) { } public void WriteString(System.ReadOnlySpan propertyName, System.ReadOnlySpan value) { } - public void WriteString(System.ReadOnlySpan propertyName, string value) { } + public void WriteString(System.ReadOnlySpan propertyName, string? value) { } public void WriteString(System.ReadOnlySpan propertyName, System.Text.Json.JsonEncodedText value) { } public void WriteString(string propertyName, System.DateTime value) { } public void WriteString(string propertyName, System.DateTimeOffset value) { } public void WriteString(string propertyName, System.Guid value) { } public void WriteString(string propertyName, System.ReadOnlySpan utf8Value) { } public void WriteString(string propertyName, System.ReadOnlySpan value) { } - public void WriteString(string propertyName, string value) { } + public void WriteString(string propertyName, string? value) { } public void WriteString(string propertyName, System.Text.Json.JsonEncodedText value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.DateTime value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.DateTimeOffset value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.Guid value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.ReadOnlySpan utf8Value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.ReadOnlySpan value) { } - public void WriteString(System.Text.Json.JsonEncodedText propertyName, string value) { } + public void WriteString(System.Text.Json.JsonEncodedText propertyName, string? value) { } public void WriteString(System.Text.Json.JsonEncodedText propertyName, System.Text.Json.JsonEncodedText value) { } public void WriteStringValue(System.DateTime value) { } public void WriteStringValue(System.DateTimeOffset value) { } public void WriteStringValue(System.Guid value) { } public void WriteStringValue(System.ReadOnlySpan utf8Value) { } public void WriteStringValue(System.ReadOnlySpan value) { } - public void WriteStringValue(string value) { } + public void WriteStringValue(string? value) { } public void WriteStringValue(System.Text.Json.JsonEncodedText value) { } } } @@ -732,8 +737,8 @@ public partial class JsonConverterAttribute : System.Text.Json.Serialization.Jso { protected JsonConverterAttribute() { } public JsonConverterAttribute(System.Type converterType) { } - public System.Type ConverterType { get { throw null; } } - public virtual System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert) { throw null; } + public System.Type? ConverterType { get { throw null; } } + public virtual System.Text.Json.Serialization.JsonConverter? CreateConverter(System.Type typeToConvert) { throw null; } } public abstract partial class JsonConverterFactory : System.Text.Json.Serialization.JsonConverter { @@ -766,7 +771,7 @@ public JsonPropertyNameAttribute(string name) { } public sealed partial class JsonStringEnumConverter : System.Text.Json.Serialization.JsonConverterFactory { public JsonStringEnumConverter() { } - public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true) { } + public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { } public override bool CanConvert(System.Type typeToConvert) { throw null; } public override System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj index 7db3c52cc0633d..dd20618e6696fe 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj @@ -1,6 +1,7 @@  net461-Debug;net461-Release;$(NetCoreAppCurrent)-Debug;$(NetCoreAppCurrent)-Release;$(NetFrameworkCurrent)-Debug;$(NetFrameworkCurrent)-Release;netstandard2.0-Debug;netstandard2.0-Release + enable diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 9daa77e7c43851..93743183338b6e 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -10,6 +10,8 @@ + $(NoWarn);nullable + enable diff --git a/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs b/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs index f53c2ab258e649..7819cddd4a9a9c 100644 --- a/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs +++ b/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace System.Collections.Generic @@ -10,7 +11,7 @@ namespace System.Collections.Generic /// Polyfills for . internal static class StackExtensions { - public static bool TryPeek(this Stack stack, out T result) + public static bool TryPeek(this Stack stack, [MaybeNullWhen(false)] out T result) { if (stack.Count > 0) { @@ -22,7 +23,7 @@ public static bool TryPeek(this Stack stack, out T result) return false; } - public static bool TryPop(this Stack stack, out T result) + public static bool TryPop(this Stack stack, [MaybeNullWhen(false)] out T result) { if (stack.Count > 0) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/BitStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/BitStack.cs index f27cf67905cbb6..65c04df9efbb2c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/BitStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/BitStack.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +#nullable enable namespace System.Text.Json { internal struct BitStack @@ -15,7 +16,7 @@ internal struct BitStack private const int DefaultInitialArraySize = 2; - private int[] _array; + private int[]? _array; // This ulong container represents a tiny stack to track the state during nested transitions. // The first bit represents the state of the current depth (1 == object, 0 == array). @@ -135,6 +136,7 @@ private bool PopFromArray() private void DoubleArray(int minSize) { + Debug.Assert(_array != null); Debug.Assert(_array.Length < int.MaxValue / 2, $"Array too large - arrayLength: {_array.Length}"); Debug.Assert(minSize >= 0 && minSize >= _array.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs index 8ee7b182bfe862..06015e0282f4b7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.MetadataDb.cs @@ -149,7 +149,7 @@ internal MetadataDb(MetadataDb source, bool useArrayPools) public void Dispose() { - byte[] data = Interlocked.Exchange(ref _data, null); + byte[]? data = Interlocked.Exchange(ref _data, null!); if (data == null) { return; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs index 76c221224c20aa..d8b19dddbe1085 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.Parse.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -118,7 +119,7 @@ public static JsonDocument Parse(Stream utf8Json, JsonDocumentOptions options = } ArraySegment drained = ReadToEnd(utf8Json); - + Debug.Assert(drained.Array != null); try { return Parse(drained.AsMemory(), options.GetReaderOptions(), drained.Array); @@ -167,7 +168,7 @@ private static async Task ParseAsyncCore( CancellationToken cancellationToken = default) { ArraySegment drained = await ReadToEndAsync(utf8Json, cancellationToken).ConfigureAwait(false); - + Debug.Assert(drained.Array != null); try { return Parse(drained.AsMemory(), options.GetReaderOptions(), drained.Array); @@ -284,7 +285,7 @@ public static JsonDocument Parse(string json, JsonDocumentOptions options = defa /// /// A value could not be read from the reader. /// - public static bool TryParseValue(ref Utf8JsonReader reader, out JsonDocument document) + public static bool TryParseValue(ref Utf8JsonReader reader, [NotNullWhen(true)] out JsonDocument? document) { return TryParseValue(ref reader, out document, shouldThrow: false); } @@ -326,12 +327,12 @@ public static bool TryParseValue(ref Utf8JsonReader reader, out JsonDocument doc /// public static JsonDocument ParseValue(ref Utf8JsonReader reader) { - bool ret = TryParseValue(ref reader, out JsonDocument document, shouldThrow: true); + bool ret = TryParseValue(ref reader, out JsonDocument? document, shouldThrow: true); Debug.Assert(ret, "TryParseValue returned false with shouldThrow: true."); - return document; + return document!; } - private static bool TryParseValue(ref Utf8JsonReader reader, out JsonDocument document, bool shouldThrow) + private static bool TryParseValue(ref Utf8JsonReader reader, [NotNullWhen(true)] out JsonDocument? document, bool shouldThrow) { JsonReaderState state = reader.CurrentState; CheckSupportedOptions(state.Options, nameof(reader)); @@ -551,7 +552,7 @@ private static bool TryParseValue(ref Utf8JsonReader reader, out JsonDocument do private static JsonDocument Parse( ReadOnlyMemory utf8Json, JsonReaderOptions readerOptions, - byte[] extraRentedBytes) + byte[]? extraRentedBytes) { ReadOnlySpan utf8JsonSpan = utf8Json.Span; var database = new MetadataDb(utf8Json.Length); @@ -577,7 +578,7 @@ private static JsonDocument Parse( private static ArraySegment ReadToEnd(Stream stream) { int written = 0; - byte[] rented = null; + byte[]? rented = null; ReadOnlySpan utf8Bom = JsonConstants.Utf8Bom; @@ -659,7 +660,7 @@ private static async CancellationToken cancellationToken) { int written = 0; - byte[] rented = null; + byte[]? rented = null; try { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.StackRowStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.StackRowStack.cs index a01b783ab491a2..83d21fbbb4e38a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.StackRowStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.StackRowStack.cs @@ -24,7 +24,7 @@ internal StackRowStack(int initialSize) public void Dispose() { byte[] toReturn = _rentedBuffer; - _rentedBuffer = null; + _rentedBuffer = null!; _topOfStack = 0; if (toReturn != null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.TryGetProperty.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.TryGetProperty.cs index 1f77e457cf0fe8..b301f0aeaea1af 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.TryGetProperty.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.TryGetProperty.cs @@ -180,7 +180,7 @@ private bool TryGetNamedPropertyValue( { int remaining = currentPropertyName.Length - idx; int written = 0; - byte[] rented = null; + byte[]? rented = null; try { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs index 865f38420edfaf..13d47b0bc50bbf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs @@ -9,6 +9,7 @@ using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Threading; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -25,8 +26,8 @@ public sealed partial class JsonDocument : IDisposable { private ReadOnlyMemory _utf8Json; private MetadataDb _parsedData; - private byte[] _extraRentedBytes; - private (int, string) _lastIndexAndString = (-1, null); + private byte[]? _extraRentedBytes; + private (int, string?) _lastIndexAndString = (-1, null); internal bool IsDisposable { get; } @@ -38,7 +39,7 @@ public sealed partial class JsonDocument : IDisposable private JsonDocument( ReadOnlyMemory utf8Json, MetadataDb parsedData, - byte[] extraRentedBytes, + byte[]? extraRentedBytes, bool isDisposable = true) { Debug.Assert(!utf8Json.IsEmpty); @@ -67,7 +68,7 @@ public void Dispose() // When "extra rented bytes exist" they contain the document, // and thus need to be cleared before being returned. - byte[] extraRentedBytes = Interlocked.Exchange(ref _extraRentedBytes, null); + byte[]? extraRentedBytes = Interlocked.Exchange(ref _extraRentedBytes, null); if (extraRentedBytes != null) { @@ -243,14 +244,15 @@ private ReadOnlyMemory GetPropertyRawValue(int valueIndex) return _utf8Json.Slice(start, end - start); } - internal string GetString(int index, JsonTokenType expectedType) + internal string? GetString(int index, JsonTokenType expectedType) { CheckNotDisposed(); - (int lastIdx, string lastString) = _lastIndexAndString; + (int lastIdx, string? lastString) = _lastIndexAndString; if (lastIdx == index) { + Debug.Assert(lastString != null); return lastString; } @@ -278,6 +280,7 @@ internal string GetString(int index, JsonTokenType expectedType) lastString = JsonReaderHelper.TranscodeHelper(segment); } + Debug.Assert(lastString != null); _lastIndexAndString = (index, lastString); return lastString; } @@ -288,14 +291,14 @@ internal bool TextEquals(int index, ReadOnlySpan otherText, bool isPropert int matchIndex = isPropertyName ? index - DbRow.Size : index; - (int lastIdx, string lastString) = _lastIndexAndString; + (int lastIdx, string? lastString) = _lastIndexAndString; if (lastIdx == matchIndex) { return otherText.SequenceEqual(lastString.AsSpan()); } - byte[] otherUtf8TextArray = null; + byte[]? otherUtf8TextArray = null; int length = checked(otherText.Length * JsonConstants.MaxExpansionFactorWhileTranscoding); Span otherUtf8Text = length <= JsonConstants.StackallocThreshold ? @@ -371,10 +374,10 @@ internal bool TextEquals(int index, ReadOnlySpan otherUtf8Text, bool isPro internal string GetNameOfPropertyValue(int index) { // The property name is one row before the property value - return GetString(index - DbRow.Size, JsonTokenType.PropertyName); + return GetString(index - DbRow.Size, JsonTokenType.PropertyName)!; } - internal bool TryGetValue(int index, out byte[] value) + internal bool TryGetValue(int index, [NotNullWhen(true)] out byte[]? value) { CheckNotDisposed(); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ArrayEnumerator.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ArrayEnumerator.cs index 3469e9b0e2e339..d7bdcb4ed4ce3f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ArrayEnumerator.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ArrayEnumerator.cs @@ -24,6 +24,7 @@ internal ArrayEnumerator(JsonElement target) { _target = target; _curIdx = -1; + Debug.Assert(target._parent != null); if (target._parent is JsonDocument document) { @@ -128,6 +129,7 @@ public bool MoveNext() } else { + Debug.Assert(_target._parent != null); var document = (JsonDocument)_target._parent; _curIdx = document.GetEndIndex(_curIdx, includeEndElement: true); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ObjectEnumerator.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ObjectEnumerator.cs index 0035340d555dc6..ca5e4911af06ff 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ObjectEnumerator.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.ObjectEnumerator.cs @@ -19,13 +19,14 @@ public struct ObjectEnumerator : IEnumerable, IEnumerator propertyName, out JsonElement valu if (jsonNode is JsonObject jsonObject) { - if (jsonObject.TryGetPropertyValue(propertyName.ToString(), out JsonNode nodeValue)) + if (jsonObject.TryGetPropertyValue(propertyName.ToString(), out JsonNode? nodeValue)) { value = nodeValue.AsJsonElement(); return true; @@ -383,7 +385,7 @@ public bool TryGetProperty(ReadOnlySpan utf8PropertyName, out JsonElement if (jsonNode is JsonObject jsonObject) { - if (jsonObject.TryGetPropertyValue(JsonHelpers.Utf8GetString(utf8PropertyName), out JsonNode nodeValue)) + if (jsonObject.TryGetPropertyValue(JsonHelpers.Utf8GetString(utf8PropertyName), out JsonNode? nodeValue)) { value = nodeValue.AsJsonElement(); return true; @@ -448,7 +450,7 @@ public bool GetBoolean() /// The parent has been disposed. /// /// - public string GetString() + public string? GetString() { CheckValidInstance(); @@ -484,7 +486,7 @@ public string GetString() /// /// The parent has been disposed. /// - public bool TryGetBytesFromBase64(out byte[] value) + public bool TryGetBytesFromBase64([NotNullWhen(true)] out byte[]? value) { CheckValidInstance(); @@ -522,7 +524,7 @@ public bool TryGetBytesFromBase64(out byte[] value) /// public byte[] GetBytesFromBase64() { - if (TryGetBytesFromBase64(out byte[] value)) + if (TryGetBytesFromBase64(out byte[]? value)) { return value; } @@ -1492,7 +1494,7 @@ internal string GetPropertyRawText() /// This method is functionally equal to doing an ordinal comparison of and /// the result of calling , but avoids creating the string instance. /// - public bool ValueEquals(string text) + public bool ValueEquals(string? text) { // CheckValidInstance is done in the helper @@ -1720,7 +1722,7 @@ public ObjectEnumerator EnumerateObject() /// /// The parent has been disposed. /// - public override string ToString() + public override string? ToString() { if (_parent is JsonNode jsonNode) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs index ac6265df3444ff..680735d5077a5b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs @@ -17,9 +17,9 @@ public readonly struct JsonProperty /// The value of this property. /// public JsonElement Value { get; } - private string _name { get; } + private string? _name { get; } - internal JsonProperty(JsonElement value, string name = null) + internal JsonProperty(JsonElement value, string? name = null) { Value = value; _name = name; @@ -45,7 +45,7 @@ internal JsonProperty(JsonElement value, string name = null) /// This method is functionally equal to doing an ordinal comparison of and /// , but can avoid creating the string instance. /// - public bool NameEquals(string text) + public bool NameEquals(string? text) { return NameEquals(text.AsSpan()); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs index 0fb5c89afeb276..2993fac38ab548 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonEncodedText.cs @@ -43,7 +43,7 @@ private JsonEncodedText(byte[] utf8Value) /// /// Thrown when the specified value is too large or if it contains invalid UTF-16 characters. /// - public static JsonEncodedText Encode(string value, JavaScriptEncoder encoder = null) + public static JsonEncodedText Encode(string value, JavaScriptEncoder? encoder = null) { if (value == null) throw new ArgumentNullException(nameof(value)); @@ -59,7 +59,7 @@ public static JsonEncodedText Encode(string value, JavaScriptEncoder encoder = n /// /// Thrown when the specified value is too large or if it contains invalid UTF-16 characters. /// - public static JsonEncodedText Encode(ReadOnlySpan value, JavaScriptEncoder encoder = null) + public static JsonEncodedText Encode(ReadOnlySpan value, JavaScriptEncoder? encoder = null) { if (value.Length == 0) { @@ -69,7 +69,7 @@ public static JsonEncodedText Encode(ReadOnlySpan value, JavaScriptEncoder return TranscodeAndEncode(value, encoder); } - private static JsonEncodedText TranscodeAndEncode(ReadOnlySpan value, JavaScriptEncoder encoder) + private static JsonEncodedText TranscodeAndEncode(ReadOnlySpan value, JavaScriptEncoder? encoder) { JsonWriterHelper.ValidateValue(value); @@ -100,7 +100,7 @@ private static JsonEncodedText TranscodeAndEncode(ReadOnlySpan value, Java /// /// Thrown when the specified value is too large or if it contains invalid UTF-8 bytes. /// - public static JsonEncodedText Encode(ReadOnlySpan utf8Value, JavaScriptEncoder encoder = null) + public static JsonEncodedText Encode(ReadOnlySpan utf8Value, JavaScriptEncoder? encoder = null) { if (utf8Value.Length == 0) { @@ -111,7 +111,7 @@ public static JsonEncodedText Encode(ReadOnlySpan utf8Value, JavaScriptEnc return EncodeHelper(utf8Value, encoder); } - private static JsonEncodedText EncodeHelper(ReadOnlySpan utf8Value, JavaScriptEncoder encoder) + private static JsonEncodedText EncodeHelper(ReadOnlySpan utf8Value, JavaScriptEncoder? encoder) { int idx = JsonWriterHelper.NeedsEscaping(utf8Value, encoder); @@ -125,12 +125,12 @@ private static JsonEncodedText EncodeHelper(ReadOnlySpan utf8Value, JavaSc } } - private static byte[] GetEscapedString(ReadOnlySpan utf8Value, int firstEscapeIndexVal, JavaScriptEncoder encoder) + private static byte[] GetEscapedString(ReadOnlySpan utf8Value, int firstEscapeIndexVal, JavaScriptEncoder? encoder) { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(firstEscapeIndexVal >= 0 && firstEscapeIndexVal < utf8Value.Length); - byte[] valueArray = null; + byte[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); @@ -174,7 +174,7 @@ public bool Equals(JsonEncodedText other) /// /// If is null, the method returns false. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is JsonEncodedText encodedText) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonException.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonException.cs index 901f5a548cca8a..787f35f1b2e288 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonException.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonException.cs @@ -14,7 +14,7 @@ namespace System.Text.Json public class JsonException : Exception { // Allow the message to mutate to avoid re-throwing and losing the StackTrace to an inner exception. - private string _message; + internal string? _message; /// /// Creates a new exception object to relay error information to the user. @@ -27,7 +27,7 @@ public class JsonException : Exception /// /// Note that the counts the number of bytes (i.e. UTF-8 code units) and not characters or scalars. /// - public JsonException(string message, string path, long? lineNumber, long? bytePositionInLine, Exception innerException) : base(message, innerException) + public JsonException(string? message, string path, long? lineNumber, long? bytePositionInLine, Exception? innerException) : base(message, innerException) { _message = message; LineNumber = lineNumber; @@ -45,7 +45,7 @@ public JsonException(string message, string path, long? lineNumber, long? bytePo /// /// Note that the counts the number of bytes (i.e. UTF-8 code units) and not characters or scalars. /// - public JsonException(string message, string path, long? lineNumber, long? bytePositionInLine) : base(message) + public JsonException(string? message, string? path, long? lineNumber, long? bytePositionInLine) : base(message) { _message = message; LineNumber = lineNumber; @@ -58,7 +58,7 @@ public JsonException(string message, string path, long? lineNumber, long? bytePo /// /// The context specific error message. /// The exception that caused the current exception. - public JsonException(string message, Exception innerException) : base(message, innerException) + public JsonException(string? message, Exception? innerException) : base(message, innerException) { _message = message; } @@ -67,7 +67,7 @@ public JsonException(string message, Exception innerException) : base(message, i /// Creates a new exception object to relay error information to the user. /// /// The context specific error message. - public JsonException(string message) : base(message) + public JsonException(string? message) : base(message) { _message = message; } @@ -125,7 +125,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont /// /// The path within the JSON where the exception was encountered. /// - public string Path { get; internal set; } + public string? Path { get; internal set; } /// /// Gets a message that describes the current exception. @@ -134,11 +134,11 @@ public override string Message { get { - return _message; + return _message ?? base.Message; } } - internal void SetMessage(string message) + internal void SetMessage(string? message) { _message = message; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 4c9f1260945750..e9fbe8fc2b9db7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -81,7 +81,7 @@ internal static string Utf8GetString(ReadOnlySpan bytes) /// /// Emulates Dictionary.TryAdd on netstandard. /// - internal static bool TryAdd(Dictionary dictionary, TKey key, TValue value) + internal static bool TryAdd(Dictionary dictionary, TKey key, TValue value) where TKey : notnull { #if NETSTANDARD2_0 || NETFRAMEWORK if (!dictionary.ContainsKey(key)) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs index 17b8ed14d75d32..5f8f7aa2128dd1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonArray.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -208,6 +209,7 @@ public JsonArray(IEnumerable values) : this() /// Index is less than 0. /// /// Null value is allowed and will be converted to the instance. + [AllowNull] public JsonNode this[int idx] { get => _list[idx]; @@ -223,7 +225,7 @@ public JsonNode this[int idx] /// /// The value to add. /// Null value is allowed and will be converted to the instance. - public void Add(JsonNode value) + public void Add(JsonNode? value) { _list.Add(value ?? JsonNull.Instance); _version++; @@ -235,7 +237,7 @@ public void Add(JsonNode value) /// The zero-based index at which should be inserted. /// The item to add. /// Null value is allowed and will be converted to the instance. - public void Insert(int index, JsonNode item) + public void Insert(int index, JsonNode? item) { _list.Insert(index, item ?? JsonNull.Instance); _version++; @@ -250,7 +252,7 @@ public void Insert(int index, JsonNode item) /// otherwise. /// /// Null value is allowed and will be converted to the instance. - public bool Contains(JsonNode value) => _list.Contains(value ?? JsonNull.Instance); + public bool Contains(JsonNode? value) => _list.Contains(value ?? JsonNull.Instance); /// /// Gets the number of elements contained in the collection. @@ -268,7 +270,7 @@ public void Insert(int index, JsonNode item) /// Item to find. /// The zero-based starting index of the search. 0 (zero) is valid in an empty collection. /// Null value is allowed and will be converted to the instance. - public int IndexOf(JsonNode item) => _list.IndexOf(item ?? JsonNull.Instance); + public int IndexOf(JsonNode? item) => _list.IndexOf(item ?? JsonNull.Instance); /// /// Returns the zero-based index of the last occurrence of a specified item in the collection. @@ -276,7 +278,7 @@ public void Insert(int index, JsonNode item) /// Item to find. /// The zero-based starting index of the search. 0 (zero) is valid in an empty collection. /// Null value is allowed and will be converted to the instance. - public int LastIndexOf(JsonNode item) => _list.LastIndexOf(item ?? JsonNull.Instance); + public int LastIndexOf(JsonNode? item) => _list.LastIndexOf(item ?? JsonNull.Instance); /// /// Removes all elements from the JSON array. @@ -298,7 +300,7 @@ public void Clear() /// otherwise. /// /// Null value is allowed and will be converted to the instance. - public bool Remove(JsonNode item) + public bool Remove(JsonNode? item) { _version++; return _list.Remove(item ?? JsonNull.Instance); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs index d98e1d401d73c7..39ecf336441e1b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonBoolean.cs @@ -38,7 +38,7 @@ public sealed class JsonBoolean : JsonNode, IEquatable /// if the boolean value of this instance matches , /// otherwise. /// - public override bool Equals(object obj) => obj is JsonBoolean jsonBoolean && Equals(jsonBoolean); + public override bool Equals(object? obj) => obj is JsonBoolean jsonBoolean && Equals(jsonBoolean); /// /// Calculates a hash code of this instance. @@ -54,7 +54,7 @@ public sealed class JsonBoolean : JsonNode, IEquatable /// if the boolean value of this instance matches , /// otherwise. /// - public bool Equals(JsonBoolean other) => !(other is null) && Value == other.Value; + public bool Equals(JsonBoolean? other) => !(other is null) && Value == other.Value; /// /// Compares values of two JSON booleans. @@ -65,7 +65,7 @@ public sealed class JsonBoolean : JsonNode, IEquatable /// if values of instances match, /// otherwise. /// - public static bool operator ==(JsonBoolean left, JsonBoolean right) + public static bool operator ==(JsonBoolean? left, JsonBoolean? right) { // Test "right" first to allow branch elimination when inlined for null checks (== null) // so it can become a simple test @@ -87,7 +87,7 @@ public sealed class JsonBoolean : JsonNode, IEquatable /// if values of instances do not match, /// otherwise. /// - public static bool operator !=(JsonBoolean left, JsonBoolean right) => !(left == right); + public static bool operator !=(JsonBoolean? left, JsonBoolean? right) => !(left == right); /// /// Creates a new JSON boolean that is a copy of the current instance. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.RecursionStackFrame.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.RecursionStackFrame.cs index ba0eaba7a0e0f3..55f9aac8b0feb9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.RecursionStackFrame.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.RecursionStackFrame.cs @@ -11,18 +11,18 @@ public abstract partial class JsonNode { private readonly struct RecursionStackFrame { - public string PropertyName { get; } - public JsonNode PropertyValue { get; } + public string? PropertyName { get; } + public JsonNode? PropertyValue { get; } public JsonValueKind ValueKind { get; } // to retrieve ValueKind when PropertyValue is null - public RecursionStackFrame(string propertyName, JsonNode propertyValue, JsonValueKind valueKind) + public RecursionStackFrame(string? propertyName, JsonNode? propertyValue, JsonValueKind valueKind) { PropertyName = propertyName; PropertyValue = propertyValue; ValueKind = valueKind; } - public RecursionStackFrame(string propertyName, JsonNode propertyValue) : this(propertyName, propertyValue, propertyValue.ValueKind) + public RecursionStackFrame(string? propertyName, JsonNode propertyValue) : this(propertyName, propertyValue, propertyValue.ValueKind) { } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.Traversal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.Traversal.cs index 5bbfc7938136f9..bf725c14eaab0d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.Traversal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.Traversal.cs @@ -30,13 +30,13 @@ public static JsonNode DeepCopy(JsonElement jsonElement) // Iterative DFS: - var currentNodes = new Stack>(); // objects/arrays currently being created - var recursionStack = new Stack>(); // null JsonElement represents end of current object/array - JsonNode toReturn = null; + var currentNodes = new Stack>(); // objects/arrays currently being created + var recursionStack = new Stack>(); // null JsonElement represents end of current object/array + JsonNode? toReturn = null; - recursionStack.Push(new KeyValuePair(null, jsonElement)); + recursionStack.Push(new KeyValuePair(null, jsonElement)); - while (recursionStack.TryPop(out KeyValuePair currentPair)) + while (recursionStack.TryPop(out KeyValuePair currentPair)) { JsonElement? currentJsonElement = currentPair.Value; @@ -44,7 +44,7 @@ public static JsonNode DeepCopy(JsonElement jsonElement) { // Current object/array is finished and can be added to its parent: - KeyValuePair nodePair = currentNodes.Pop(); + KeyValuePair nodePair = currentNodes.Pop(); Debug.Assert(nodePair.Value is JsonArray || nodePair.Value is JsonObject); @@ -59,51 +59,53 @@ public static JsonNode DeepCopy(JsonElement jsonElement) var jsonObject = new JsonObject(); // Add jsonObject to current nodes: - currentNodes.Push(new KeyValuePair(currentPair.Key, jsonObject)); + currentNodes.Push(new KeyValuePair(currentPair.Key, jsonObject)); // Add end of object marker: - recursionStack.Push(new KeyValuePair(null, null)); + recursionStack.Push(new KeyValuePair(null, null)); // Add properties to recursion stack. Reverse enumerate to keep properties order: foreach (JsonProperty property in currentJsonElement.Value.EnumerateObject().Reverse()) { - recursionStack.Push(new KeyValuePair(property.Name, property.Value)); + recursionStack.Push(new KeyValuePair(property.Name, property.Value)); } break; case JsonValueKind.Array: var jsonArray = new JsonArray(); // Add jsonArray to current nodes: - currentNodes.Push(new KeyValuePair(currentPair.Key, jsonArray)); + currentNodes.Push(new KeyValuePair(currentPair.Key, jsonArray)); // Add end of array marker: - recursionStack.Push(new KeyValuePair(null, null)); + recursionStack.Push(new KeyValuePair(null, null)); // Add elements to recursion stack. Reverse enumerate to keep items order: foreach (JsonElement element in currentJsonElement.Value.EnumerateArray().Reverse()) { - recursionStack.Push(new KeyValuePair(null, element)); + recursionStack.Push(new KeyValuePair(null, element)); } break; case JsonValueKind.Number: var jsonNumber = new JsonNumber(currentJsonElement.Value.GetRawText()); - AddToParent(new KeyValuePair(currentPair.Key, jsonNumber), ref currentNodes, ref toReturn); + AddToParent(new KeyValuePair(currentPair.Key, jsonNumber), ref currentNodes, ref toReturn); break; case JsonValueKind.String: - var jsonString = new JsonString(currentJsonElement.Value.GetString()); - AddToParent(new KeyValuePair(currentPair.Key, jsonString), ref currentNodes, ref toReturn); + string? value = currentJsonElement.Value.GetString(); + Debug.Assert(value != null); + var jsonString = new JsonString(value); + AddToParent(new KeyValuePair(currentPair.Key, jsonString), ref currentNodes, ref toReturn); break; case JsonValueKind.True: var jsonBooleanTrue = new JsonBoolean(true); - AddToParent(new KeyValuePair(currentPair.Key, jsonBooleanTrue), ref currentNodes, ref toReturn); + AddToParent(new KeyValuePair(currentPair.Key, jsonBooleanTrue), ref currentNodes, ref toReturn); break; case JsonValueKind.False: var jsonBooleanFalse = new JsonBoolean(false); - AddToParent(new KeyValuePair(currentPair.Key, jsonBooleanFalse), ref currentNodes, ref toReturn); + AddToParent(new KeyValuePair(currentPair.Key, jsonBooleanFalse), ref currentNodes, ref toReturn); break; case JsonValueKind.Null: var jsonNull = JsonNull.Instance; - AddToParent(new KeyValuePair(currentPair.Key, jsonNull), ref currentNodes, ref toReturn); + AddToParent(new KeyValuePair(currentPair.Key, jsonNull), ref currentNodes, ref toReturn); break; default: Debug.Assert(jsonElement.ValueKind == JsonValueKind.Undefined, "No handler for JsonValueKind.{jsonElement.ValueKind}"); @@ -126,17 +128,17 @@ public static JsonNode Parse(string json, JsonNodeOptions options = default) { Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json), options.GetReaderOptions()); - var currentNodes = new Stack>(); // nodes currently being created - JsonNode toReturn = null; + var currentNodes = new Stack>(); // nodes currently being created + JsonNode? toReturn = null; while (reader.Read()) { JsonTokenType tokenType = reader.TokenType; - currentNodes.TryPeek(out KeyValuePair currentPair); + currentNodes.TryPeek(out KeyValuePair currentPair); void AddNewPair(JsonNode jsonNode, bool keepInCurrentNodes = false) { - KeyValuePair newProperty; + KeyValuePair newProperty; if (currentPair.Value == null) { @@ -147,18 +149,18 @@ void AddNewPair(JsonNode jsonNode, bool keepInCurrentNodes = false) { // Create as property, keep name, replace null with new JsonNode: currentNodes.Pop(); - newProperty = new KeyValuePair(currentPair.Key, jsonNode); + newProperty = new KeyValuePair(currentPair.Key, jsonNode); } else { // Add first JsonNode: - newProperty = new KeyValuePair(null, jsonNode); + newProperty = new KeyValuePair(null, jsonNode); } } else { // Create as value: - newProperty = new KeyValuePair(null, jsonNode); + newProperty = new KeyValuePair(null, jsonNode); } if (keepInCurrentNodes) @@ -195,13 +197,13 @@ void AddNewPair(JsonNode jsonNode, bool keepInCurrentNodes = false) AddToParent(currentPair, ref currentNodes, ref toReturn, options.DuplicatePropertyNameHandling); break; case JsonTokenType.PropertyName: - currentNodes.Push(new KeyValuePair(reader.GetString(), null)); + currentNodes.Push(new KeyValuePair(reader.GetString(), null)); break; case JsonTokenType.Number: AddNewPair(new JsonNumber(JsonHelpers.Utf8GetString(reader.ValueSpan))); break; case JsonTokenType.String: - AddNewPair(new JsonString(reader.GetString())); + AddNewPair(new JsonString(reader.GetString()!)); break; case JsonTokenType.True: AddNewPair(new JsonBoolean(true)); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.TraversalHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.TraversalHelpers.cs index 90f8f55a6271c0..7e52a73ddaa12e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.TraversalHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.TraversalHelpers.cs @@ -13,12 +13,12 @@ namespace System.Text.Json public abstract partial class JsonNode { private static void AddToParent( - KeyValuePair nodePair, - ref Stack> currentNodes, - ref JsonNode toReturn, + KeyValuePair nodePair, + ref Stack> currentNodes, + ref JsonNode? toReturn, DuplicatePropertyNameHandlingStrategy duplicatePropertyNameHandling = DuplicatePropertyNameHandlingStrategy.Replace) { - if (currentNodes.TryPeek(out KeyValuePair parentPair)) + if (currentNodes.TryPeek(out KeyValuePair parentPair)) { // Parent needs to be JsonObject or JsonArray Debug.Assert(parentPair.Value is JsonObject || parentPair.Value is JsonArray); @@ -42,7 +42,7 @@ private static void AddToParent( } else { - jsonObject.Add(nodePair); + jsonObject.Add(nodePair!); } } else if (parentPair.Value is JsonArray jsonArray) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs index 3d2a50d1467982..b3c632f14ffc7d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + namespace System.Text.Json { /// @@ -33,7 +36,15 @@ private protected JsonNode() { } /// /// Provided was not built from . /// - public static JsonNode GetNode(JsonElement jsonElement) => !jsonElement.IsImmutable ? (JsonNode)jsonElement._parent : throw new ArgumentException(SR.NotNodeJsonElementParent); + public static JsonNode GetNode(JsonElement jsonElement) + { + if (jsonElement.IsImmutable) + { + throw new ArgumentException(SR.NotNodeJsonElementParent); + } + Debug.Assert(jsonElement._parent != null); + return (JsonNode)jsonElement._parent; + } /// /// Gets the represented by the . @@ -46,10 +57,11 @@ private protected JsonNode() { } /// if the operation succeded; /// otherwise, /// - public static bool TryGetNode(JsonElement jsonElement, out JsonNode jsonNode) + public static bool TryGetNode(JsonElement jsonElement, [NotNullWhen(true)] out JsonNode? jsonNode) { if (!jsonElement.IsImmutable) { + Debug.Assert(jsonElement._parent != null); jsonNode = (JsonNode)jsonElement._parent; return true; } @@ -71,7 +83,7 @@ public static bool TryGetNode(JsonElement jsonElement, out JsonNode jsonNode) /// /// Null value is accepted and will be interpreted as . /// - public static implicit operator JsonNode(string value) + public static implicit operator JsonNode(string? value) { if (value == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNull.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNull.cs index bb48216e936bb9..857bd2c5128ebf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNull.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNull.cs @@ -30,7 +30,7 @@ public JsonNull() { } /// if the is , /// otherwise. /// - public override bool Equals(object obj) => obj is JsonNull; + public override bool Equals(object? obj) => obj is JsonNull; /// /// Calculates a hash code of this instance. @@ -46,7 +46,7 @@ public JsonNull() { } /// if is not null, /// otherwise. /// - public bool Equals(JsonNull other) => !(other is null); + public bool Equals(JsonNull? other) => !(other is null); /// /// Compares values of two JSON nulls. @@ -57,7 +57,7 @@ public JsonNull() { } /// if both instances match, /// otherwise. /// - public static bool operator ==(JsonNull left, JsonNull right) + public static bool operator ==(JsonNull? left, JsonNull? right) { // Test "right" first to allow branch elimination when inlined for null checks (== null) // so it can become a simple test @@ -79,7 +79,7 @@ public JsonNull() { } /// if both instances do not match, /// otherwise. /// - public static bool operator !=(JsonNull left, JsonNull right) => !(left == right); + public static bool operator !=(JsonNull? left, JsonNull? right) => !(left == right); /// /// Creates a new JSON null that is a copy of the current instance. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs index 2935e252c399e6..8a0146aaf491b7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNumber.cs @@ -11,7 +11,7 @@ namespace System.Text.Json /// public sealed class JsonNumber : JsonNode, IEquatable { - private string _value; + private string _value = null!; /// /// Initializes a new instance of the class representing the value 0. @@ -557,7 +557,7 @@ public void SetDouble(double value) /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// - public override bool Equals(object obj) => obj is JsonNumber jsonNumber && Equals(jsonNumber); + public override bool Equals(object? obj) => obj is JsonNumber jsonNumber && Equals(jsonNumber); /// /// Calculates a hash code of this instance. @@ -573,7 +573,7 @@ public void SetDouble(double value) /// if the value of this instance matches exactly (is equal and has the same format), /// otherwise. /// - public bool Equals(JsonNumber other) => !(other is null) && _value == other._value; + public bool Equals(JsonNumber? other) => !(other is null) && _value == other._value; /// /// Compares values of two JSON numbers. @@ -584,7 +584,7 @@ public void SetDouble(double value) /// if values of instances match exactly (are equal and have the same format), /// otherwise. /// - public static bool operator ==(JsonNumber left, JsonNumber right) + public static bool operator ==(JsonNumber? left, JsonNumber? right) { // Test "right" first to allow branch elimination when inlined for null checks (== null) // so it can become a simple test @@ -606,7 +606,7 @@ public void SetDouble(double value) /// if values of instances do not match exactly (are not equal or have different format), /// otherwise. /// - public static bool operator !=(JsonNumber left, JsonNumber right) => !(left == right); + public static bool operator !=(JsonNumber? left, JsonNumber? right) => !(left == right); /// /// Creates a new JSON number that is a copy of the current instance. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs index fbc9531d4695b8..4b1a336ed51c5c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -13,8 +14,8 @@ namespace System.Text.Json public sealed class JsonObject : JsonNode, IEnumerable> { internal readonly Dictionary _dictionary; - internal JsonObjectProperty _first; - internal JsonObjectProperty _last; + internal JsonObjectProperty? _first; + internal JsonObjectProperty? _last; internal int _version; /// @@ -29,7 +30,7 @@ public JsonObject() /// Initializes a new instance of the class representing provided set of JSON properties. /// /// >Properties to represent as a JSON object. - public JsonObject(IEnumerable> jsonProperties) + public JsonObject(IEnumerable> jsonProperties) : this() => AddRange(jsonProperties); @@ -40,6 +41,7 @@ public JsonObject(IEnumerable> jsonProperties) /// /// Provided property name is null. /// + [AllowNull] public JsonNode this[string propertyName] { get => propertyName != null ? GetPropertyValue(propertyName) : throw new ArgumentNullException(nameof(propertyName)); @@ -70,7 +72,7 @@ public JsonNode this[string propertyName] /// /// Property name to add already exists. /// - public void Add(KeyValuePair jsonProperty) => Add(jsonProperty.Key, jsonProperty.Value); + public void Add(KeyValuePair jsonProperty) => Add(jsonProperty.Key, jsonProperty.Value); /// /// Adds the specified property to the JSON object. @@ -84,7 +86,7 @@ public JsonNode this[string propertyName] /// Property name to add already exists. /// /// Null value is allowed and will be converted to the instance. - public void Add(string propertyName, JsonNode propertyValue) + public void Add(string propertyName, JsonNode? propertyValue) { if (propertyName == null) { @@ -127,9 +129,9 @@ public void Add(string propertyName, JsonNode propertyValue) /// /// Some of the property names are null. /// - public void AddRange(IEnumerable> jsonProperties) + public void AddRange(IEnumerable> jsonProperties) { - foreach (KeyValuePair property in jsonProperties) + foreach (KeyValuePair property in jsonProperties) { Add(property); } @@ -154,7 +156,7 @@ public bool Remove(string propertyName) } #if BUILDING_INBOX_LIBRARY - if (_dictionary.Remove(propertyName, out JsonObjectProperty value)) + if (_dictionary.Remove(propertyName, out JsonObjectProperty? value)) { AdjustLinkedListPointers(value); _version++; @@ -202,7 +204,7 @@ public bool Remove(string propertyName, StringComparison stringComparison) throw new ArgumentNullException(nameof(propertyName)); } - JsonObjectProperty _current = _first; + JsonObjectProperty? _current = _first; while (_current != null && !string.Equals(_current.Name, propertyName, stringComparison)) { @@ -298,7 +300,7 @@ public bool ContainsProperty(string propertyName, StringComparison stringCompari /// public JsonNode GetPropertyValue(string propertyName) { - if (!TryGetPropertyValue(propertyName, out JsonNode jsonNode)) + if (!TryGetPropertyValue(propertyName, out JsonNode? jsonNode)) { throw new KeyNotFoundException(SR.Format(SR.PropertyNotFound, propertyName)); } @@ -320,7 +322,7 @@ public JsonNode GetPropertyValue(string propertyName) /// public JsonNode GetPropertyValue(string propertyName, StringComparison stringComparison) { - if (!TryGetPropertyValue(propertyName, stringComparison, out JsonNode jsonNode)) + if (!TryGetPropertyValue(propertyName, stringComparison, out JsonNode? jsonNode)) { throw new KeyNotFoundException(SR.Format(SR.PropertyNotFound, propertyName)); } @@ -340,9 +342,9 @@ public JsonNode GetPropertyValue(string propertyName, StringComparison stringCom /// /// When this method returns , the value of is meaningless. /// - public bool TryGetPropertyValue(string propertyName, out JsonNode jsonNode) + public bool TryGetPropertyValue(string propertyName, [NotNullWhen(true)] out JsonNode? jsonNode) { - if (_dictionary.TryGetValue(propertyName, out JsonObjectProperty jsonObjectProperty)) + if (_dictionary.TryGetValue(propertyName, out JsonObjectProperty? jsonObjectProperty)) { jsonNode = jsonObjectProperty.Value; return true; @@ -368,7 +370,7 @@ public bool TryGetPropertyValue(string propertyName, out JsonNode jsonNode) /// /// If is set to , calling this method is equivalent to calling . /// - public bool TryGetPropertyValue(string propertyName, StringComparison stringComparison, out JsonNode jsonNode) + public bool TryGetPropertyValue(string propertyName, StringComparison stringComparison, [NotNullWhen(true)] out JsonNode? jsonNode) { if (stringComparison == StringComparison.Ordinal) { @@ -443,9 +445,9 @@ public JsonObject GetJsonObjectPropertyValue(string propertyName, StringComparis /// if JSON object property with specified name was found; /// otherwise, /// - public bool TryGetJsonObjectPropertyValue(string propertyName, out JsonObject jsonObject) + public bool TryGetJsonObjectPropertyValue(string propertyName, [NotNullWhen(true)] out JsonObject? jsonObject) { - if (TryGetPropertyValue(propertyName, out JsonNode jsonNode)) + if (TryGetPropertyValue(propertyName, out JsonNode? jsonNode)) { jsonObject = jsonNode as JsonObject; return jsonObject != null; @@ -468,9 +470,9 @@ public bool TryGetJsonObjectPropertyValue(string propertyName, out JsonObject js /// /// If is set to , calling this method is equivalent to calling . /// - public bool TryGetJsonObjectPropertyValue(string propertyName, StringComparison stringComparison, out JsonObject jsonObject) + public bool TryGetJsonObjectPropertyValue(string propertyName, StringComparison stringComparison, [NotNullWhen(true)] out JsonObject? jsonObject) { - if (TryGetPropertyValue(propertyName, stringComparison, out JsonNode jsonNode)) + if (TryGetPropertyValue(propertyName, stringComparison, out JsonNode? jsonNode)) { jsonObject = jsonNode as JsonObject; return jsonObject != null; @@ -535,9 +537,9 @@ public JsonArray GetJsonArrayPropertyValue(string propertyName, StringComparison /// if JSON array property with specified name was found; /// otherwise, /// - public bool TryGetJsonArrayPropertyValue(string propertyName, out JsonArray jsonArray) + public bool TryGetJsonArrayPropertyValue(string propertyName, [NotNullWhen(true)] out JsonArray? jsonArray) { - if (TryGetPropertyValue(propertyName, out JsonNode jsonNode)) + if (TryGetPropertyValue(propertyName, out JsonNode? jsonNode)) { jsonArray = jsonNode as JsonArray; return jsonArray != null; @@ -560,9 +562,9 @@ public bool TryGetJsonArrayPropertyValue(string propertyName, out JsonArray json /// /// If is set to , calling this method is equivalent to calling . /// - public bool TryGetJsonArrayPropertyValue(string propertyName, StringComparison stringComparison, out JsonArray jsonArray) + public bool TryGetJsonArrayPropertyValue(string propertyName, StringComparison stringComparison, [NotNullWhen(true)] out JsonArray? jsonArray) { - if (TryGetPropertyValue(propertyName, stringComparison, out JsonNode jsonNode)) + if (TryGetPropertyValue(propertyName, stringComparison, out JsonNode? jsonNode)) { jsonArray = jsonNode as JsonArray; return jsonArray != null; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectEnumerator.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectEnumerator.cs index 856c3bedfd3872..4d520703275023 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectEnumerator.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectEnumerator.cs @@ -8,8 +8,8 @@ namespace System.Text.Json /// public struct JsonObjectEnumerator : IEnumerator> { - private JsonObjectProperty _first; - private JsonObjectProperty _current; + private JsonObjectProperty? _first; + private JsonObjectProperty? _current; /// /// Initializes a new instance of the class supporting an interation over provided JSON object. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectProperty.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectProperty.cs index 7e40518373a52f..ad48415377ffb1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectProperty.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObjectProperty.cs @@ -8,10 +8,10 @@ internal class JsonObjectProperty { internal string Name { get; } internal JsonNode Value { get; set; } - internal JsonObjectProperty Prev { get; set; } - internal JsonObjectProperty Next { get; set; } + internal JsonObjectProperty? Prev { get; set; } + internal JsonObjectProperty? Next { get; set; } - public JsonObjectProperty(string name, JsonNode value, JsonObjectProperty prev, JsonObjectProperty next) + public JsonObjectProperty(string name, JsonNode value, JsonObjectProperty? prev, JsonObjectProperty? next) { Name = name; Value = value; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonString.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonString.cs index 3b34dbb4ed925d..b7df7060373413 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonString.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonString.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -13,7 +14,7 @@ namespace System.Text.Json /// public sealed class JsonString : JsonNode, IEquatable { - private string _value; + private string _value = null!; /// /// Initializes a new instance of the class representing the empty value. @@ -149,7 +150,7 @@ public string Value /// if the text value of this instance matches , /// otherwise. /// - public override bool Equals(object obj) => obj is JsonString jsonString && Equals(jsonString); + public override bool Equals(object? obj) => obj is JsonString jsonString && Equals(jsonString); /// /// Calculates a hash code of this instance. @@ -165,7 +166,7 @@ public string Value /// if the text value of this instance matches , /// otherwise. /// - public bool Equals(JsonString other) => !(other is null) && Value == other.Value; + public bool Equals(JsonString? other) => !(other is null) && Value == other.Value; /// /// Compares values of two JSON strings. @@ -176,7 +177,7 @@ public string Value /// if values of instances match, /// otherwise. /// - public static bool operator ==(JsonString left, JsonString right) + public static bool operator ==(JsonString? left, JsonString? right) { // Test "right" first to allow branch elimination when inlined for null checks (== null) // so it can become a simple test @@ -198,7 +199,7 @@ public string Value /// if values of instances do not match, /// otherwise. /// - public static bool operator !=(JsonString left, JsonString right) => !(left == right); + public static bool operator !=(JsonString? left, JsonString? right) => !(left == right); /// /// Creates a new JSON string that is a copy of the current instance. @@ -222,7 +223,7 @@ public string Value /// /// if text was converted successfully; othwerwise returns . /// - internal bool TryGetBytesFromBase64(out byte[] value) + internal bool TryGetBytesFromBase64([NotNullWhen(true)] out byte[]? value) { Debug.Assert(_value != null); @@ -238,7 +239,7 @@ internal bool TryGetBytesFromBase64(out byte[] value) // be /4 * 3 - padding. To be on the safe side, keep padding and slice later int bufferSize = _value.Length / 4 * 3; - byte[] arrayToReturnToPool = null; + byte[]? arrayToReturnToPool = null; Span buffer = bufferSize <= JsonConstants.StackallocThreshold ? stackalloc byte[JsonConstants.StackallocThreshold] : arrayToReturnToPool = ArrayPool.Shared.Rent(bufferSize); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs index fa4502b62329c7..bed38869cffc81 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs @@ -5,14 +5,15 @@ using System.Buffers; using System.Buffers.Text; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { internal static partial class JsonReaderHelper { - public static bool TryGetUnescapedBase64Bytes(ReadOnlySpan utf8Source, int idx, out byte[] bytes) + public static bool TryGetUnescapedBase64Bytes(ReadOnlySpan utf8Source, int idx, [NotNullWhen(true)] out byte[]? bytes) { - byte[] unescapedArray = null; + byte[]? unescapedArray = null; Span utf8Unescaped = utf8Source.Length <= JsonConstants.StackallocThreshold ? stackalloc byte[utf8Source.Length] : @@ -41,7 +42,7 @@ public static bool TryGetUnescapedBase64Bytes(ReadOnlySpan utf8Source, int // TODO: Similar to escaping, replace the unescaping logic with publicly shipping APIs from https://github.com/dotnet/corefx/issues/33509 public static string GetUnescapedString(ReadOnlySpan utf8Source, int idx) { - byte[] unescapedArray = null; + byte[]? unescapedArray = null; Span utf8Unescaped = utf8Source.Length <= JsonConstants.StackallocThreshold ? stackalloc byte[utf8Source.Length] : @@ -68,7 +69,7 @@ public static bool UnescapeAndCompare(ReadOnlySpan utf8Source, ReadOnlySpa { Debug.Assert(utf8Source.Length >= other.Length && utf8Source.Length / JsonConstants.MaxExpansionFactorWhileEscaping <= other.Length); - byte[] unescapedArray = null; + byte[]? unescapedArray = null; Span utf8Unescaped = utf8Source.Length <= JsonConstants.StackallocThreshold ? stackalloc byte[utf8Source.Length] : @@ -96,8 +97,8 @@ public static bool UnescapeAndCompare(ReadOnlySequence utf8Source, ReadOnl Debug.Assert(!utf8Source.IsSingleSegment); Debug.Assert(utf8Source.Length >= other.Length && utf8Source.Length / JsonConstants.MaxExpansionFactorWhileEscaping <= other.Length); - byte[] escapedArray = null; - byte[] unescapedArray = null; + byte[]? escapedArray = null; + byte[]? unescapedArray = null; int length = checked((int)utf8Source.Length); @@ -132,7 +133,7 @@ public static bool UnescapeAndCompare(ReadOnlySequence utf8Source, ReadOnl return result; } - public static bool TryDecodeBase64InPlace(Span utf8Unescaped, out byte[] bytes) + public static bool TryDecodeBase64InPlace(Span utf8Unescaped, [NotNullWhen(true)] out byte[]? bytes) { OperationStatus status = Base64.DecodeFromUtf8InPlace(utf8Unescaped, out int bytesWritten); if (status != OperationStatus.Done) @@ -144,9 +145,9 @@ public static bool TryDecodeBase64InPlace(Span utf8Unescaped, out byte[] b return true; } - public static bool TryDecodeBase64(ReadOnlySpan utf8Unescaped, out byte[] bytes) + public static bool TryDecodeBase64(ReadOnlySpan utf8Unescaped, [NotNullWhen(true)] out byte[]? bytes) { - byte[] pooledArray = null; + byte[]? pooledArray = null; Span byteSpan = utf8Unescaped.Length <= JsonConstants.StackallocThreshold ? stackalloc byte[utf8Unescaped.Length] : diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.TryGet.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.TryGet.cs index 66e9701b5ab6fc..642d4a6db5f1bf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.TryGet.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.TryGet.cs @@ -5,6 +5,7 @@ using System.Buffers; using System.Buffers.Text; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -23,7 +24,7 @@ public ref partial struct Utf8JsonReader /// /// It will also throw when the JSON string contains invalid UTF-8 bytes, or invalid UTF-16 surrogates. /// - public string GetString() + public string? GetString() { if (TokenType == JsonTokenType.Null) { @@ -106,7 +107,7 @@ public bool GetBoolean() /// public byte[] GetBytesFromBase64() { - if (!TryGetBytesFromBase64(out byte[] value)) + if (!TryGetBytesFromBase64(out byte[]? value)) { throw ThrowHelper.GetFormatException(DataType.Base64String); } @@ -457,7 +458,7 @@ public Guid GetGuid() /// Thrown if trying to get the value of a JSON token that is not a . /// /// - public bool TryGetBytesFromBase64(out byte[] value) + public bool TryGetBytesFromBase64([NotNullWhen(true)] out byte[]? value) { if (TokenType != JsonTokenType.String) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs index cd1fe9bc2ddf97..517a5641c20051 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs @@ -458,7 +458,7 @@ public bool ValueTextEquals(ReadOnlySpan utf8Text) /// if required. The look up text is matched as is, without any modifications to it. /// /// - public bool ValueTextEquals(string text) + public bool ValueTextEquals(string? text) { return ValueTextEquals(text.AsSpan()); } @@ -511,7 +511,7 @@ public bool ValueTextEquals(ReadOnlySpan text) return false; } - byte[] otherUtf8TextArray = null; + byte[]? otherUtf8TextArray = null; Span otherUtf8Text; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultArrayConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultArrayConverter.cs index 529d5428ef68c2..a7e4602c1fb9af 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultArrayConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultArrayConverter.cs @@ -19,7 +19,7 @@ public override IEnumerable CreateFromList(ref ReadStack state, IList sourceList array = Array.CreateInstance(probe.GetType(), sourceList.Count); int i = 0; - foreach (IList child in sourceList) + foreach (IList? child in sourceList) { if (child is Array childArray) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableDictionaryConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableDictionaryConverter.cs index 57893d373d026d..e19a5f51d75473 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableDictionaryConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableDictionaryConverter.cs @@ -28,11 +28,10 @@ public static void RegisterImmutableDictionary(Type immutableCollectionType, Typ } // Get the constructing type. - Type constructingType = underlyingType.Assembly.GetType(constructingTypeName); + Type constructingType = underlyingType.Assembly.GetType(constructingTypeName)!; // Create a delegate which will point to the CreateRange method. - ImmutableCollectionCreator createRangeDelegate; - createRangeDelegate = options.MemberAccessorStrategy.ImmutableDictionaryCreateRange(constructingType, immutableCollectionType, elementType); + ImmutableCollectionCreator createRangeDelegate = options.MemberAccessorStrategy.ImmutableDictionaryCreateRange(constructingType, immutableCollectionType, elementType); // Cache the delegate options.TryAddCreateRangeDelegate(delegateKey, createRangeDelegate); @@ -58,9 +57,9 @@ public static bool IsImmutableDictionary(Type type) public override object CreateFromDictionary(ref ReadStack state, IDictionary sourceDictionary, JsonSerializerOptions options) { - Type immutableCollectionType = state.Current.JsonPropertyInfo.RuntimePropertyType; + Type immutableCollectionType = state.Current.JsonPropertyInfo!.RuntimePropertyType; - JsonClassInfo elementClassInfo = state.Current.JsonPropertyInfo.ElementClassInfo; + JsonClassInfo elementClassInfo = state.Current.JsonPropertyInfo.ElementClassInfo!; Type elementType = elementClassInfo.Type; string delegateKey = DefaultImmutableEnumerableConverter.GetDelegateKey(immutableCollectionType, elementType, out _, out _); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableEnumerableConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableEnumerableConverter.cs index 2ae8b2e3b9b8d9..b347bb59ea1bdf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableEnumerableConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/DefaultImmutableEnumerableConverter.cs @@ -92,11 +92,10 @@ public static void RegisterImmutableCollection(Type immutableCollectionType, Typ } // Get the constructing type. - Type constructingType = underlyingType.Assembly.GetType(constructingTypeName); + Type constructingType = underlyingType.Assembly.GetType(constructingTypeName)!; // Create a delegate which will point to the CreateRange method. - ImmutableCollectionCreator createRangeDelegate; - createRangeDelegate = options.MemberAccessorStrategy.ImmutableCollectionCreateRange(constructingType, immutableCollectionType, elementType); + ImmutableCollectionCreator createRangeDelegate = options.MemberAccessorStrategy.ImmutableCollectionCreateRange(constructingType, immutableCollectionType, elementType); // Cache the delegate options.TryAddCreateRangeDelegate(delegateKey, createRangeDelegate); @@ -129,9 +128,9 @@ public static bool IsImmutableEnumerable(Type type) public override IEnumerable CreateFromList(ref ReadStack state, IList sourceList, JsonSerializerOptions options) { - Type immutableCollectionType = state.Current.JsonPropertyInfo.RuntimePropertyType; + Type immutableCollectionType = state.Current.JsonPropertyInfo!.RuntimePropertyType; - JsonClassInfo elementClassInfo = state.Current.JsonPropertyInfo.ElementClassInfo; + JsonClassInfo elementClassInfo = state.Current.JsonPropertyInfo.ElementClassInfo!; Type elementType = elementClassInfo.Type; string delegateKey = GetDelegateKey(immutableCollectionType, elementType, out _, out _); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonConverterEnum.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonConverterEnum.cs index d8e7aad387db98..bbdd499ae62359 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonConverterEnum.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonConverterEnum.cs @@ -28,7 +28,7 @@ public override JsonConverter CreateConverter(Type type, JsonSerializerOptions o BindingFlags.Instance | BindingFlags.Public, binder: null, new object[] { EnumConverterOptions.AllowNumbers }, - culture: null); + culture: null)!; return converter; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonKeyValuePairConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonKeyValuePairConverter.cs index 8fa37cbfb586f3..75032665f60c25 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonKeyValuePairConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonKeyValuePairConverter.cs @@ -30,7 +30,7 @@ public override JsonConverter CreateConverter(Type type, JsonSerializerOptions o BindingFlags.Instance | BindingFlags.Public, binder: null, args: null, - culture: null); + culture: null)!; return converter; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterChar.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterChar.cs index a7e7995f280e4d..f225ae40395f46 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterChar.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterChar.cs @@ -10,7 +10,12 @@ internal sealed class JsonConverterChar : JsonConverter { public override char Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return reader.GetString()[0]; + string? str = reader.GetString(); + if (string.IsNullOrEmpty(str) || str.Length > 1) + { + throw ThrowHelper.GetInvalidOperationException_ExpectedChar(reader.TokenType); + } + return str[0]; } public override void Write(Utf8JsonWriter writer, char value, JsonSerializerOptions options) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterEnum.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterEnum.cs index d7ab4e19c2e7a2..65f6dbf1980daa 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterEnum.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterEnum.cs @@ -14,11 +14,11 @@ internal class JsonConverterEnum : JsonConverter private static readonly TypeCode s_enumTypeCode = Type.GetTypeCode(typeof(T)); // Odd type codes are conveniently signed types (for enum backing types). - private static readonly string s_negativeSign = ((int)s_enumTypeCode % 2) == 0 ? null : NumberFormatInfo.CurrentInfo.NegativeSign; + private static readonly string? s_negativeSign = ((int)s_enumTypeCode % 2) == 0 ? null : NumberFormatInfo.CurrentInfo.NegativeSign; private readonly EnumConverterOptions _converterOptions; private readonly JsonNamingPolicy _namingPolicy; - private readonly ConcurrentDictionary _nameCache; + private readonly ConcurrentDictionary? _nameCache; public override bool CanConvert(Type type) { @@ -30,7 +30,7 @@ public JsonConverterEnum(EnumConverterOptions options) { } - public JsonConverterEnum(EnumConverterOptions options, JsonNamingPolicy namingPolicy) + public JsonConverterEnum(EnumConverterOptions options, JsonNamingPolicy? namingPolicy) { _converterOptions = options; if (namingPolicy != null) @@ -57,7 +57,7 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial } // Try parsing case sensitive first - string enumString = reader.GetString(); + string? enumString = reader.GetString(); if (!Enum.TryParse(enumString, out T value) && !Enum.TryParse(enumString, ignoreCase: true, out value)) { @@ -158,7 +158,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions if (_converterOptions.HasFlag(EnumConverterOptions.AllowStrings)) { string original = value.ToString(); - if (_nameCache != null && _nameCache.TryGetValue(original, out string transformed)) + if (_nameCache != null && _nameCache.TryGetValue(original, out string? transformed)) { writer.WriteStringValue(transformed); return; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterKeyValuePair.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterKeyValuePair.cs index ff9fe09bfa61b0..384f62e5b798ad 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterKeyValuePair.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterKeyValuePair.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json.Serialization.Converters { @@ -24,10 +25,10 @@ public override KeyValuePair Read(ref Utf8JsonReader reader, Type ThrowHelper.ThrowJsonException(); } - TKey k = default; + TKey k = default!; bool keySet = false; - TValue v = default; + TValue v = default!; bool valueSet = false; // Get the first property. @@ -37,7 +38,7 @@ public override KeyValuePair Read(ref Utf8JsonReader reader, Type ThrowHelper.ThrowJsonException(); } - string propertyName = reader.GetString(); + string propertyName = reader.GetString()!; if (propertyName == KeyName) { k = ReadProperty(ref reader, typeToConvert, options); @@ -60,7 +61,7 @@ public override KeyValuePair Read(ref Utf8JsonReader reader, Type ThrowHelper.ThrowJsonException(); } - propertyName = reader.GetString(); + propertyName = reader.GetString()!; if (propertyName == ValueName) { v = ReadProperty(ref reader, typeToConvert, options); @@ -110,7 +111,7 @@ private T ReadProperty(ref Utf8JsonReader reader, Type typeToConvert, JsonSer return k; } - private void WriteProperty(Utf8JsonWriter writer, T value, JsonEncodedText name, JsonSerializerOptions options) + private void WriteProperty(Utf8JsonWriter writer, T value, JsonEncodedText name, JsonSerializerOptions? options) { Type typeToConvert = typeof(T); @@ -128,7 +129,7 @@ private void WriteProperty(Utf8JsonWriter writer, T value, JsonEncodedText na } } - public override void Write(Utf8JsonWriter writer, KeyValuePair value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, KeyValuePair value, JsonSerializerOptions? options) { writer.WriteStartObject(); WriteProperty(writer, value.Key, _keyName, options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterString.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterString.cs index e3a9b705ed9c24..598b059c8a2b0e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterString.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterString.cs @@ -4,14 +4,14 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class JsonConverterString : JsonConverter + internal sealed class JsonConverterString : JsonConverter { - public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.GetString(); } - public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options) { writer.WriteStringValue(value); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterUri.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterUri.cs index a819050909c2cc..0a8215210640bf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterUri.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonValueConverterUri.cs @@ -8,8 +8,8 @@ internal sealed class JsonConverterUri : JsonConverter { public override Uri Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - string uriString = reader.GetString(); - if (Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out Uri value)) + string? uriString = reader.GetString(); + if (Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out Uri? value)) { return value; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ImmutableCollectionCreator.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ImmutableCollectionCreator.cs index efdfb1809ad941..8c093f0f54fed0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ImmutableCollectionCreator.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ImmutableCollectionCreator.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Text.Json @@ -12,14 +13,14 @@ namespace System.Text.Json internal abstract class ImmutableCollectionCreator { public abstract void RegisterCreatorDelegateFromMethod(MethodInfo creator); - public abstract bool CreateImmutableEnumerable(IList items, out IEnumerable collection); - public abstract bool CreateImmutableDictionary(IDictionary items, out IDictionary collection); + public abstract bool CreateImmutableEnumerable(IList items, [NotNullWhen(true)] out IEnumerable? collection); + public abstract bool CreateImmutableDictionary(IDictionary items, [NotNullWhen(true)] out IDictionary? collection); } internal sealed class ImmutableEnumerableCreator : ImmutableCollectionCreator where TCollection : IEnumerable { - private Func, TCollection> _creatorDelegate; + private Func, TCollection>? _creatorDelegate; public override void RegisterCreatorDelegateFromMethod(MethodInfo creator) { @@ -27,14 +28,14 @@ public override void RegisterCreatorDelegateFromMethod(MethodInfo creator) _creatorDelegate = (Func, TCollection>)creator.CreateDelegate(typeof(Func, TCollection>)); } - public override bool CreateImmutableEnumerable(IList items, out IEnumerable collection) + public override bool CreateImmutableEnumerable(IList items, [NotNullWhen(true)] out IEnumerable collection) { Debug.Assert(_creatorDelegate != null); collection = _creatorDelegate(CreateGenericTElementIEnumerable(items)); return true; } - public override bool CreateImmutableDictionary(IDictionary items, out IDictionary collection) + public override bool CreateImmutableDictionary(IDictionary items, [NotNullWhen(true)] out IDictionary? collection) { // Shouldn't be calling this method for immutable dictionaries. collection = default; @@ -43,9 +44,9 @@ public override bool CreateImmutableDictionary(IDictionary items, out IDictionar private IEnumerable CreateGenericTElementIEnumerable(IList sourceList) { - foreach (object item in sourceList) + foreach (object? item in sourceList) { - yield return (TElement)item; + yield return (TElement)item!; } } } @@ -53,7 +54,7 @@ private IEnumerable CreateGenericTElementIEnumerable(IList sourceList) internal sealed class ImmutableDictionaryCreator : ImmutableCollectionCreator where TCollection : IReadOnlyDictionary { - private Func>, TCollection> _creatorDelegate; + private Func>, TCollection>? _creatorDelegate; public override void RegisterCreatorDelegateFromMethod(MethodInfo creator) { @@ -62,14 +63,14 @@ public override void RegisterCreatorDelegateFromMethod(MethodInfo creator) typeof(Func>, TCollection>)); } - public override bool CreateImmutableEnumerable(IList items, out IEnumerable collection) + public override bool CreateImmutableEnumerable(IList items, [NotNullWhen(true)] out IEnumerable? collection) { // Shouldn't be calling this method for immutable non-dictionaries. collection = default; return false; } - public override bool CreateImmutableDictionary(IDictionary items, out IDictionary collection) + public override bool CreateImmutableDictionary(IDictionary items, [NotNullWhen(true)] out IDictionary collection) { Debug.Assert(_creatorDelegate != null); collection = (IDictionary)_creatorDelegate(CreateGenericTElementIDictionary(items)); @@ -78,9 +79,12 @@ public override bool CreateImmutableDictionary(IDictionary items, out IDictionar private IEnumerable> CreateGenericTElementIDictionary(IDictionary sourceDictionary) { - foreach (DictionaryEntry item in sourceDictionary) + foreach (DictionaryEntry? item in sourceDictionary) { - yield return new KeyValuePair((string)item.Key, (TElement)item.Value); + if (item.HasValue) + { + yield return new KeyValuePair((string)item.Value.Key, (TElement)item.Value.Value!); + } } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.AddProperty.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.AddProperty.cs index 7337db0f24c8a8..fb91bafd4e78ea 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.AddProperty.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.AddProperty.cs @@ -26,10 +26,10 @@ private JsonPropertyInfo AddProperty(Type propertyType, PropertyInfo propertyInf parentClassType, propertyInfo, out Type runtimeType, - out Type elementType, - out Type nullableUnderlyingType, + out Type? elementType, + out Type? nullableUnderlyingType, out _, - out JsonConverter converter, + out JsonConverter? converter, checkForAddMethod: false, options); @@ -50,11 +50,11 @@ private JsonPropertyInfo AddProperty(Type propertyType, PropertyInfo propertyInf internal static JsonPropertyInfo CreateProperty( Type declaredPropertyType, Type runtimePropertyType, - PropertyInfo propertyInfo, + PropertyInfo? propertyInfo, Type parentClassType, - Type collectionElementType, - Type nullableUnderlyingType, - JsonConverter converter, + Type? collectionElementType, + Type? nullableUnderlyingType, + JsonConverter? converter, ClassType classType, JsonSerializerOptions options) { @@ -65,11 +65,11 @@ internal static JsonPropertyInfo CreateProperty( if (treatAsNullable && converter != null) { - propertyInfoClassType = typeof(JsonPropertyInfoNullable<,>).MakeGenericType(parentClassType, nullableUnderlyingType); + propertyInfoClassType = typeof(JsonPropertyInfoNullable<,>).MakeGenericType(parentClassType, nullableUnderlyingType!); } else { - Type typeToConvert = converter?.TypeToConvert; + Type? typeToConvert = converter?.TypeToConvert; if (typeToConvert == null) { typeToConvert = declaredPropertyType; @@ -103,7 +103,7 @@ internal static JsonPropertyInfo CreateProperty( BindingFlags.Instance | BindingFlags.Public, binder: null, args: null, - culture: null); + culture: null)!; jsonPropertyInfo.Initialize( parentClassType, @@ -128,9 +128,9 @@ internal static JsonPropertyInfo CreateProperty( internal static JsonPropertyInfo CreatePolicyProperty( Type declaredPropertyType, Type runtimePropertyType, - Type elementType, - Type nullableUnderlyingType, - JsonConverter converter, + Type? elementType, + Type? nullableUnderlyingType, + JsonConverter? converter, ClassType classType, JsonSerializerOptions options) { @@ -151,7 +151,7 @@ internal static JsonPropertyInfo CreatePolicyProperty( /// internal JsonPropertyInfo CreateRootProperty(JsonSerializerOptions options) { - JsonConverter converter = options.DetermineConverterForProperty(Type, Type, propertyInfo: null); + JsonConverter? converter = options.DetermineConverterForProperty(Type, Type, propertyInfo: null); return CreateProperty( declaredPropertyType: Type, @@ -174,10 +174,10 @@ static JsonPropertyInfo CreateRuntimeProperty((JsonPropertyInfo property, Type r arg.classType, key.property.PropertyInfo, out _, - out Type elementType, - out Type nullableType, + out Type? elementType, + out Type? nullableType, out _, - out JsonConverter converter, + out JsonConverter? converter, checkForAddMethod: false, arg.options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs index 1b0dcdd38bbf58..dcc2a92e18dd15 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -25,28 +26,28 @@ internal sealed partial class JsonClassInfo private const int PropertyNameCountCacheThreshold = 64; // All of the serializable properties on a POCO (except the optional extension property) keyed on property name. - public volatile Dictionary PropertyCache; + public volatile Dictionary? PropertyCache; // Serializable runtime/polymorphic properties, keyed on property and runtime type. - public ConcurrentDictionary<(JsonPropertyInfo, Type), JsonPropertyInfo> RuntimePropertyCache; + public ConcurrentDictionary<(JsonPropertyInfo, Type), JsonPropertyInfo>? RuntimePropertyCache; // All of the serializable properties on a POCO including the optional extension property. // Used for performance during serialization instead of 'PropertyCache' above. - public volatile JsonPropertyInfo[] PropertyCacheArray; + public volatile JsonPropertyInfo[]? PropertyCacheArray; // Fast cache of properties by first JSON ordering; may not contain all properties. Accessed before PropertyCache. // Use an array (instead of List) for highest performance. - private volatile PropertyRef[] _propertyRefsSorted; + private volatile PropertyRef[]? _propertyRefsSorted; - public delegate object ConstructorDelegate(); - public ConstructorDelegate CreateObject { get; private set; } + public delegate object? ConstructorDelegate(); + public ConstructorDelegate? CreateObject { get; private set; } public ClassType ClassType { get; private set; } - public JsonPropertyInfo DataExtensionProperty { get; private set; } + public JsonPropertyInfo? DataExtensionProperty { get; private set; } // If enumerable, the JsonClassInfo for the element type. - private JsonClassInfo _elementClassInfo; + private JsonClassInfo? _elementClassInfo; /// /// Return the JsonClassInfo for the element type, or null if the type is not an enumerable or dictionary. @@ -55,7 +56,7 @@ internal sealed partial class JsonClassInfo /// This should not be called during warm-up (initial creation of JsonClassInfos) to avoid recursive behavior /// which could result in a StackOverflowException. /// - public JsonClassInfo ElementClassInfo + public JsonClassInfo? ElementClassInfo { get { @@ -71,7 +72,7 @@ public JsonClassInfo ElementClassInfo } } - public Type ElementType { get; set; } + public Type? ElementType { get; set; } public JsonSerializerOptions Options { get; private set; } @@ -123,10 +124,10 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) parentClassType: type, propertyInfo: null, out Type runtimeType, - out Type elementType, - out Type nullableUnderlyingType, - out MethodInfo addMethod, - out JsonConverter converter, + out Type? elementType, + out Type? nullableUnderlyingType, + out MethodInfo? addMethod, + out JsonConverter? converter, checkForAddMethod: true, options); @@ -154,7 +155,7 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) propertyInfo.SetMethod?.IsPublic == true) { JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); - Debug.Assert(jsonPropertyInfo != null); + Debug.Assert(jsonPropertyInfo != null && jsonPropertyInfo.NameAsString != null); // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. if (!JsonHelpers.TryAdd(cache, jsonPropertyInfo.NameAsString, jsonPropertyInfo)) @@ -179,7 +180,7 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) if (DetermineExtensionDataProperty(cache)) { // Remove from cache since it is handled independently. - cache.Remove(DataExtensionProperty.NameAsString); + cache.Remove(DataExtensionProperty!.NameAsString!); cacheArray = new JsonPropertyInfo[cache.Count + 1]; @@ -228,7 +229,7 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) private bool DetermineExtensionDataProperty(Dictionary cache) { - JsonPropertyInfo jsonPropertyInfo = GetPropertyWithUniqueAttribute(typeof(JsonExtensionDataAttribute), cache); + JsonPropertyInfo? jsonPropertyInfo = GetPropertyWithUniqueAttribute(typeof(JsonExtensionDataAttribute), cache); if (jsonPropertyInfo != null) { Type declaredPropertyType = jsonPropertyInfo.DeclaredPropertyType; @@ -245,13 +246,14 @@ private bool DetermineExtensionDataProperty(Dictionary return false; } - private JsonPropertyInfo GetPropertyWithUniqueAttribute(Type attributeType, Dictionary cache) + private JsonPropertyInfo? GetPropertyWithUniqueAttribute(Type attributeType, Dictionary cache) { - JsonPropertyInfo property = null; + JsonPropertyInfo? property = null; foreach (JsonPropertyInfo jsonPropertyInfo in cache.Values) { - Attribute attribute = jsonPropertyInfo.PropertyInfo.GetCustomAttribute(attributeType); + Debug.Assert(jsonPropertyInfo.PropertyInfo != null); + Attribute? attribute = jsonPropertyInfo.PropertyInfo.GetCustomAttribute(attributeType); if (attribute != null) { if (property != null) @@ -270,10 +272,10 @@ private JsonPropertyInfo GetPropertyWithUniqueAttribute(Type attributeType, Dict [MethodImpl(MethodImplOptions.AggressiveInlining)] public JsonPropertyInfo GetProperty(ReadOnlySpan propertyName, ref ReadStackFrame frame) { - JsonPropertyInfo info = null; + JsonPropertyInfo? info = null; // Keep a local copy of the cache in case it changes by another thread. - PropertyRef[] localPropertyRefsSorted = _propertyRefsSorted; + PropertyRef[]? localPropertyRefsSorted = _propertyRefsSorted; ulong key = GetKey(propertyName); @@ -396,12 +398,12 @@ private Dictionary CreatePropertyCache(int capacity) return new Dictionary(capacity, comparer); } - public JsonPropertyInfo PolicyProperty { get; private set; } + public JsonPropertyInfo? PolicyProperty { get; private set; } - public MethodInfo AddItemToObject { get; private set; } + public MethodInfo? AddItemToObject { get; private set; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool TryIsPropertyRefEqual(in PropertyRef propertyRef, ReadOnlySpan propertyName, ulong key, ref JsonPropertyInfo info) + private static bool TryIsPropertyRefEqual(in PropertyRef propertyRef, ReadOnlySpan propertyName, ulong key, [NotNullWhen(true)] ref JsonPropertyInfo? info) { if (key == propertyRef.Key) { @@ -519,12 +521,12 @@ public static ulong GetKey(ReadOnlySpan propertyName) public static ClassType GetClassType( Type type, Type parentClassType, - PropertyInfo propertyInfo, + PropertyInfo? propertyInfo, out Type runtimeType, - out Type elementType, - out Type nullableUnderlyingType, - out MethodInfo addMethod, - out JsonConverter converter, + out Type? elementType, + out Type? nullableUnderlyingType, + out MethodInfo? addMethod, + out JsonConverter? converter, bool checkForAddMethod, JsonSerializerOptions options) { @@ -582,26 +584,30 @@ public static ClassType GetClassType( return ClassType.Enumerable; } - if (type.FullName.StartsWith("System.Collections.Generic.IEnumerable`1")) + if (type.FullName != null) { - elementType = type.GetGenericArguments()[0]; - runtimeType = typeof(List<>).MakeGenericType(elementType); - addMethod = default; - return ClassType.Enumerable; - } - else if (type.FullName.StartsWith("System.Collections.Generic.IDictionary`2") || - type.FullName.StartsWith("System.Collections.Generic.IReadOnlyDictionary`2")) - { - Type[] genericTypes = type.GetGenericArguments(); + if (type.FullName.StartsWith("System.Collections.Generic.IEnumerable`1")) + { + elementType = type.GetGenericArguments()[0]; + runtimeType = typeof(List<>).MakeGenericType(elementType); + addMethod = default; + return ClassType.Enumerable; + } + else if (type.FullName.StartsWith("System.Collections.Generic.IDictionary`2") || + type.FullName.StartsWith("System.Collections.Generic.IReadOnlyDictionary`2")) + { + Type[] genericTypes = type.GetGenericArguments(); - elementType = genericTypes[1]; - runtimeType = typeof(Dictionary<,>).MakeGenericType(genericTypes[0], elementType); - addMethod = default; - return ClassType.Dictionary; + elementType = genericTypes[1]; + runtimeType = typeof(Dictionary<,>).MakeGenericType(genericTypes[0], elementType); + addMethod = default; + return ClassType.Dictionary; + } } + { - Type genericIDictionaryType = type.GetInterface("System.Collections.Generic.IDictionary`2") ?? type.GetInterface("System.Collections.Generic.IReadOnlyDictionary`2"); + Type? genericIDictionaryType = type.GetInterface("System.Collections.Generic.IDictionary`2") ?? type.GetInterface("System.Collections.Generic.IReadOnlyDictionary`2"); if (genericIDictionaryType != null) { Type[] genericTypes = genericIDictionaryType.GetGenericArguments(); @@ -641,7 +647,7 @@ public static ClassType GetClassType( } { - Type genericIEnumerableType = type.GetInterface("System.Collections.Generic.IEnumerable`1"); + Type? genericIEnumerableType = type.GetInterface("System.Collections.Generic.IEnumerable`1"); if (genericIEnumerableType != null) { @@ -690,7 +696,7 @@ public static ClassType GetClassType( if (checkForAddMethod) { - Type genericICollectionType = type.GetInterface("System.Collections.Generic.ICollection`1"); + Type? genericICollectionType = type.GetInterface("System.Collections.Generic.ICollection`1"); if (genericICollectionType != null) { addMethod = genericICollectionType.GetMethod("Add"); @@ -698,7 +704,7 @@ public static ClassType GetClassType( else { // Non-immutable stack or queue. - MethodInfo methodInfo = type.GetMethod("Push") ?? type.GetMethod("Enqueue"); + MethodInfo? methodInfo = type.GetMethod("Push") ?? type.GetMethod("Enqueue"); if (methodInfo?.ReturnType == typeof(void)) { addMethod = methodInfo; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs index 1bee8212319922..ea06f03a3a42ad 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs @@ -19,6 +19,6 @@ internal JsonConverter() { } public abstract bool CanConvert(Type typeToConvert); // This is used internally to quickly determine the type being converted for JsonConverter. - internal virtual Type TypeToConvert => null; + internal virtual Type? TypeToConvert => null; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterAttribute.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterAttribute.cs index 2d0573a809d488..51095cd5c7b125 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterAttribute.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterAttribute.cs @@ -34,7 +34,7 @@ protected JsonConverterAttribute() { } /// /// The type of the converter to create, or null if should be used to obtain the converter. /// - public Type ConverterType { get; private set; } + public Type? ConverterType { get; private set; } /// /// If overridden and is null, allows a custom attribute to create the converter in order to pass additional state. @@ -42,7 +42,7 @@ protected JsonConverterAttribute() { } /// /// The custom converter. /// - public virtual JsonConverter CreateConverter(Type typeToConvert) + public virtual JsonConverter? CreateConverter(Type typeToConvert) { return null; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs index 35cdd393d674e2..d96ec3574ef2c7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs @@ -19,7 +19,7 @@ public abstract class JsonConverterFactory : JsonConverter /// protected JsonConverterFactory() { } - internal JsonConverter GetConverterInternal(Type typeToConvert, JsonSerializerOptions options) + internal JsonConverter? GetConverterInternal(Type typeToConvert, JsonSerializerOptions options) { Debug.Assert(CanConvert(typeToConvert)); return CreateConverter(typeToConvert, options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs index d9c378e2931cea..3b890e01aa1f85 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfo.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Converters; @@ -20,17 +21,18 @@ internal abstract class JsonPropertyInfo public static readonly JsonPropertyInfo s_missingProperty = GetMissingProperty(); - private JsonClassInfo _elementClassInfo; - private JsonClassInfo _runtimeClassInfo; - private JsonClassInfo _declaredTypeClassInfo; + private JsonClassInfo? _elementClassInfo; + private JsonClassInfo? _runtimeClassInfo; + private JsonClassInfo? _declaredTypeClassInfo; - private JsonPropertyInfo _dictionaryValuePropertyPolicy; + private JsonPropertyInfo? _dictionaryValuePropertyPolicy; public bool CanBeNull { get; private set; } public ClassType ClassType; - public abstract JsonConverter ConverterBase { get; set; } + [DisallowNull] + public abstract JsonConverter? ConverterBase { get; set; } private static JsonPropertyInfo GetMissingProperty() { @@ -60,7 +62,7 @@ public void CopyRuntimeSettingsTo(JsonPropertyInfo other) // Create a property that is ignored at run-time. It uses the same type (typeof(sbyte)) to help // prevent issues with unsupported types and helps ensure we don't accidently (de)serialize it. - public static JsonPropertyInfo CreateIgnoredPropertyPlaceholder(PropertyInfo propertyInfo, JsonSerializerOptions options) + public static JsonPropertyInfo CreateIgnoredPropertyPlaceholder(PropertyInfo? propertyInfo, JsonSerializerOptions options) { JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfoNotNullable(); jsonPropertyInfo.Options = options; @@ -73,7 +75,7 @@ public static JsonPropertyInfo CreateIgnoredPropertyPlaceholder(PropertyInfo pro return jsonPropertyInfo; } - public Type DeclaredPropertyType { get; private set; } + public Type DeclaredPropertyType { get; private set; } = null!; private void DeterminePropertyName() { @@ -82,7 +84,7 @@ private void DeterminePropertyName() return; } - JsonPropertyNameAttribute nameAttribute = GetAttribute(PropertyInfo); + JsonPropertyNameAttribute? nameAttribute = GetAttribute(PropertyInfo); if (nameAttribute != null) { string name = nameAttribute.Name; @@ -152,11 +154,13 @@ private void DetermineSerializationCapabilities() } else if (ClassType == ClassType.Dictionary && DefaultImmutableDictionaryConverter.IsImmutableDictionary(RuntimePropertyType)) { + Debug.Assert(ElementType != null); DefaultImmutableDictionaryConverter.RegisterImmutableDictionary(RuntimePropertyType, ElementType, Options); DictionaryConverter = s_jsonImmutableDictionaryConverter; } else if (ClassType == ClassType.Enumerable && DefaultImmutableEnumerableConverter.IsImmutableEnumerable(RuntimePropertyType)) { + Debug.Assert(ElementType != null); DefaultImmutableEnumerableConverter.RegisterImmutableCollection(RuntimePropertyType, ElementType, Options); EnumerableConverter = s_jsonImmutableEnumerableConverter; } @@ -183,9 +187,9 @@ public JsonPropertyInfo DictionaryValuePropertyPolicy if (_dictionaryValuePropertyPolicy == null) { // Use the existing PolicyProperty if there is one. - if ((_dictionaryValuePropertyPolicy = ElementClassInfo.PolicyProperty) == null) + if ((_dictionaryValuePropertyPolicy = ElementClassInfo!.PolicyProperty) == null) { - Type dictionaryValueType = ElementType; + Type? dictionaryValueType = ElementType; Debug.Assert(dictionaryValueType != null); _dictionaryValuePropertyPolicy = JsonClassInfo.CreatePolicyProperty( @@ -210,7 +214,7 @@ public JsonPropertyInfo DictionaryValuePropertyPolicy /// This should not be called during warm-up (initial creation of JsonClassInfos) to avoid recursive behavior /// which could result in a StackOverflowException. /// - public JsonClassInfo ElementClassInfo + public JsonClassInfo? ElementClassInfo { get { @@ -225,23 +229,23 @@ public JsonClassInfo ElementClassInfo } } - public Type ElementType { get; set; } + public Type? ElementType { get; set; } - public JsonEnumerableConverter EnumerableConverter { get; private set; } - public JsonDictionaryConverter DictionaryConverter { get; private set; } + public JsonEnumerableConverter? EnumerableConverter { get; private set; } + public JsonDictionaryConverter? DictionaryConverter { get; private set; } // The escaped name passed to the writer. // Use a field here (not a property) to avoid value semantics. public JsonEncodedText? EscapedName; - public static TAttribute GetAttribute(PropertyInfo propertyInfo) where TAttribute : Attribute + public static TAttribute? GetAttribute(PropertyInfo propertyInfo) where TAttribute : Attribute { - return (TAttribute)propertyInfo?.GetCustomAttribute(typeof(TAttribute), inherit: false); + return (TAttribute?)propertyInfo.GetCustomAttribute(typeof(TAttribute), inherit: false); } public abstract Type GetDictionaryConcreteType(); - public void GetDictionaryKeyAndValue(ref WriteStackFrame writeStackFrame, out string key, out object value) + public void GetDictionaryKeyAndValue(ref WriteStackFrame writeStackFrame, out string key, out object? value) { Debug.Assert(ClassType == ClassType.Dictionary); @@ -256,7 +260,7 @@ public void GetDictionaryKeyAndValue(ref WriteStackFrame writeStackFrame, out st else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - writeStackFrame.JsonPropertyInfo.DeclaredPropertyType, + writeStackFrame.JsonPropertyInfo!.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } @@ -268,7 +272,7 @@ public void GetDictionaryKeyAndValue(ref WriteStackFrame writeStackFrame, out st } } - public abstract void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object value); + public abstract void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object? value); public virtual void GetPolicies() { @@ -277,7 +281,7 @@ public virtual void GetPolicies() IgnoreNullValues = Options.IgnoreNullValues; } - public abstract object GetValueAsObject(object obj); + public abstract object? GetValueAsObject(object? obj); public bool HasGetter { get; set; } public bool HasSetter { get; set; } @@ -289,9 +293,9 @@ public virtual void Initialize( Type declaredPropertyType, Type runtimePropertyType, ClassType runtimeClassType, - PropertyInfo propertyInfo, - Type elementType, - JsonConverter converter, + PropertyInfo? propertyInfo, + Type? elementType, + JsonConverter? converter, bool treatAsNullable, JsonSerializerOptions options) { @@ -312,17 +316,17 @@ public virtual void Initialize( } } - public abstract bool TryCreateEnumerableAddMethod(object target, out object addMethodDelegate); + public abstract bool TryCreateEnumerableAddMethod(object target, [NotNullWhen(true)] out object? addMethodDelegate); - public abstract object CreateEnumerableAddMethod(MethodInfo addMethod, object target); + public abstract object? CreateEnumerableAddMethod(MethodInfo addMethod, object target); - public abstract void AddObjectToEnumerableWithReflection(object addMethodDelegate, object value); + public abstract void AddObjectToEnumerableWithReflection(object addMethodDelegate, object? value); - public abstract void AddObjectToParentEnumerable(object addMethodDelegate, object value); + public abstract void AddObjectToParentEnumerable(object addMethodDelegate, object? value); - public abstract void AddObjectToDictionary(object target, string key, object value); + public abstract void AddObjectToDictionary(object target, string key, object? value); - public abstract void AddObjectToParentDictionary(object target, string key, object value); + public abstract void AddObjectToParentDictionary(object target, string key, object? value); public abstract bool CanPopulateDictionary(object target); @@ -333,17 +337,17 @@ public virtual void Initialize( public bool IsPropertyPolicy { get; protected set; } // The name from a Json value. This is cached for performance on first deserialize. - public byte[] JsonPropertyName { get; set; } + public byte[]? JsonPropertyName { get; set; } // The name of the property with any casing policy or the name specified from JsonPropertyNameAttribute. - public byte[] Name { get; private set; } - public string NameAsString { get; private set; } + public byte[]? Name { get; private set; } + public string? NameAsString { get; private set; } // Key for fast property name lookup. public ulong PropertyNameKey { get; set; } // Options can be referenced here since all JsonPropertyInfos originate from a JsonClassInfo that is cached on JsonSerializerOptions. - protected JsonSerializerOptions Options { get; set; } + protected JsonSerializerOptions Options { get; set; } = null!; // initialized in Init method protected abstract void OnRead(ref ReadStack state, ref Utf8JsonReader reader); protected abstract void OnReadEnumerable(ref ReadStack state, ref Utf8JsonReader reader); @@ -351,16 +355,16 @@ public virtual void Initialize( protected virtual void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { } protected abstract void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonWriter writer); - public Type ParentClassType { get; private set; } + public Type ParentClassType { get; private set; } = null!; - public PropertyInfo PropertyInfo { get; private set; } + public PropertyInfo? PropertyInfo { get; private set; } public void Read(JsonTokenType tokenType, ref ReadStack state, ref Utf8JsonReader reader) { Debug.Assert(ShouldDeserialize); - JsonPropertyInfo propertyInfo; - JsonClassInfo elementClassInfo = ElementClassInfo; + JsonPropertyInfo? propertyInfo; + JsonClassInfo? elementClassInfo = ElementClassInfo; if (elementClassInfo != null && (propertyInfo = elementClassInfo.PolicyProperty) != null) { if (!state.Current.CollectionPropertyInitialized) @@ -455,9 +459,9 @@ public JsonClassInfo DeclaredTypeClassInfo } } - public Type RuntimePropertyType { get; private set; } + public Type RuntimePropertyType { get; private set; } = null!; - public abstract void SetValueAsObject(object obj, object value); + public abstract void SetValueAsObject(object? obj, object? value); public bool ShouldSerialize { get; private set; } public bool ShouldDeserialize { get; private set; } @@ -514,8 +518,11 @@ public void Write(ref WriteStack state, Utf8JsonWriter writer) if (state.Current.CollectionEnumerator != null) { + Debug.Assert(ElementClassInfo != null); + // Forward the setter to the value-based JsonPropertyInfo. - JsonPropertyInfo propertyInfo = ElementClassInfo.PolicyProperty; + JsonPropertyInfo? propertyInfo = ElementClassInfo.PolicyProperty; + Debug.Assert(propertyInfo != null); propertyInfo.WriteEnumerable(ref state, writer); } // For performance on release build, don't verify converter correctness for internal converters. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoCommon.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoCommon.cs index 7b9c78ed22e736..a67879610b5b26 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoCommon.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoCommon.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json.Serialization; @@ -15,21 +16,19 @@ namespace System.Text.Json /// internal abstract class JsonPropertyInfoCommon : JsonPropertyInfo { - public Func Get { get; private set; } - public Action Set { get; private set; } + public Func? Get { get; private set; } + public Action? Set { get; private set; } - public Action AddItemToEnumerable { get; private set; } - - public JsonConverter Converter { get; internal set; } + public JsonConverter? Converter { get; internal set; } public override void Initialize( Type parentClassType, Type declaredPropertyType, Type runtimePropertyType, ClassType runtimeClassType, - PropertyInfo propertyInfo, - Type elementType, - JsonConverter converter, + PropertyInfo? propertyInfo, + Type? elementType, + JsonConverter? converter, bool treatAsNullable, JsonSerializerOptions options) { @@ -68,7 +67,8 @@ public override void Initialize( GetPolicies(); } - public override JsonConverter ConverterBase + [DisallowNull] + public override JsonConverter? ConverterBase { get { @@ -83,7 +83,7 @@ public override JsonConverter ConverterBase } } - public override object GetValueAsObject(object obj) + public override object? GetValueAsObject(object? obj) { if (IsPropertyPolicy) { @@ -91,40 +91,41 @@ public override object GetValueAsObject(object obj) } Debug.Assert(HasGetter); - return Get(obj); + return Get!(obj); } - public override void SetValueAsObject(object obj, object value) + public override void SetValueAsObject(object? obj, object? value) { Debug.Assert(HasSetter); - TDeclaredProperty typedValue = (TDeclaredProperty)value; + TDeclaredProperty typedValue = (TDeclaredProperty)value!; if (typedValue != null || !IgnoreNullValues) { - Set(obj, typedValue); + Set!(obj, typedValue); } } - private JsonPropertyInfo _elementPropertyInfo; + private JsonPropertyInfo? _elementPropertyInfo; private void SetPropertyInfoForObjectElement() { + Debug.Assert(ElementClassInfo != null); if (_elementPropertyInfo == null && ElementClassInfo.PolicyProperty == null) { _elementPropertyInfo = ElementClassInfo.CreateRootProperty(Options); } } - public override bool TryCreateEnumerableAddMethod(object target, out object addMethodDelegate) + public override bool TryCreateEnumerableAddMethod(object target, [NotNullWhen(true)] out object? addMethodDelegate) { SetPropertyInfoForObjectElement(); - Debug.Assert((_elementPropertyInfo ?? ElementClassInfo.PolicyProperty) != null); + Debug.Assert((_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty) != null); - addMethodDelegate = (_elementPropertyInfo ?? ElementClassInfo.PolicyProperty).CreateEnumerableAddMethod(RuntimeClassInfo.AddItemToObject, target); + addMethodDelegate = (_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty!).CreateEnumerableAddMethod(RuntimeClassInfo.AddItemToObject!, target); return addMethodDelegate != null; } - public override object CreateEnumerableAddMethod(MethodInfo addMethod, object target) + public override object? CreateEnumerableAddMethod(MethodInfo addMethod, object target) { if (target is ICollection collection && collection.IsReadOnly) { @@ -134,29 +135,29 @@ public override object CreateEnumerableAddMethod(MethodInfo addMethod, object ta return Options.MemberAccessorStrategy.CreateAddDelegate(addMethod, target); } - public override void AddObjectToEnumerableWithReflection(object addMethodDelegate, object value) + public override void AddObjectToEnumerableWithReflection(object addMethodDelegate, object? value) { - Debug.Assert((_elementPropertyInfo ?? ElementClassInfo.PolicyProperty) != null); - (_elementPropertyInfo ?? ElementClassInfo.PolicyProperty).AddObjectToParentEnumerable(addMethodDelegate, value); + Debug.Assert((_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty) != null); + (_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty!).AddObjectToParentEnumerable(addMethodDelegate, value); } - public override void AddObjectToParentEnumerable(object addMethodDelegate, object value) + public override void AddObjectToParentEnumerable(object addMethodDelegate, object? value) { - ((Action)addMethodDelegate)((TDeclaredProperty)value); + ((Action)addMethodDelegate)((TDeclaredProperty)value!); } - public override void AddObjectToDictionary(object target, string key, object value) + public override void AddObjectToDictionary(object target, string key, object? value) { - Debug.Assert((_elementPropertyInfo ?? ElementClassInfo.PolicyProperty) != null); - (_elementPropertyInfo ?? ElementClassInfo.PolicyProperty).AddObjectToParentDictionary(target, key, value); + Debug.Assert((_elementPropertyInfo ?? ElementClassInfo?.PolicyProperty) != null); + (_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty!).AddObjectToParentDictionary(target, key, value); } - public override void AddObjectToParentDictionary(object target, string key, object value) + public override void AddObjectToParentDictionary(object target, string key, object? value) { if (target is IDictionary genericDict) { Debug.Assert(!genericDict.IsReadOnly); - genericDict[key] = (TDeclaredProperty)value; + genericDict[key] = (TDeclaredProperty)value!; } else { @@ -167,8 +168,8 @@ public override void AddObjectToParentDictionary(object target, string key, obje public override bool CanPopulateDictionary(object target) { SetPropertyInfoForObjectElement(); - Debug.Assert((_elementPropertyInfo ?? ElementClassInfo.PolicyProperty) != null); - return (_elementPropertyInfo ?? ElementClassInfo.PolicyProperty).ParentDictionaryCanBePopulated(target); + Debug.Assert((_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty) != null); + return (_elementPropertyInfo ?? ElementClassInfo!.PolicyProperty!).ParentDictionaryCanBePopulated(target); } public override bool ParentDictionaryCanBePopulated(object target) @@ -179,7 +180,7 @@ public override bool ParentDictionaryCanBePopulated(object target) } else if (target is IDictionary dict && !dict.IsReadOnly) { - Type genericDictType = target.GetType().GetInterface("System.Collections.Generic.IDictionary`2") ?? + Type? genericDictType = target.GetType().GetInterface("System.Collections.Generic.IDictionary`2") ?? target.GetType().GetInterface("System.Collections.Generic.IReadOnlyDictionary`2"); if (genericDictType != null && genericDictType.GetGenericArguments()[0] != typeof(string)) @@ -208,9 +209,9 @@ public override IDictionary CreateConverterDictionary() // CreateRange method to create and return the desired immutable collection type. public override IEnumerable CreateImmutableCollectionInstance(ref ReadStack state, Type collectionType, string delegateKey, IList sourceList, JsonSerializerOptions options) { - IEnumerable collection = null; + IEnumerable? collection = null; - if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator creator) || + if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator? creator) || !creator.CreateImmutableEnumerable(sourceList, out collection)) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(collectionType, state.JsonPath()); @@ -224,9 +225,9 @@ public override IEnumerable CreateImmutableCollectionInstance(ref ReadStack stat // CreateRange method to create and return the desired immutable collection type. public override IDictionary CreateImmutableDictionaryInstance(ref ReadStack state, Type collectionType, string delegateKey, IDictionary sourceDictionary, JsonSerializerOptions options) { - IDictionary collection = null; + IDictionary? collection = null; - if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator creator) || + if (!options.TryGetCreateRangeDelegate(delegateKey, out ImmutableCollectionCreator? creator) || !creator.CreateImmutableDictionary(sourceDictionary, out collection)) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(collectionType, state.JsonPath()); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs index 752ad363097a80..df6f1b4f68ca1d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullable.cs @@ -30,6 +30,7 @@ protected override void OnRead(ref ReadStack state, ref Utf8JsonReader reader) } else { + Debug.Assert(Set != null); Set(state.Current.ReturnValue, value); } } @@ -63,11 +64,12 @@ protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writ TConverter value; if (IsPropertyPolicy) { - value = (TConverter)current.CurrentValue; + value = (TConverter)current.CurrentValue!; } else { - value = (TConverter)Get(current.CurrentValue); + Debug.Assert(Get != null); + value = (TConverter)Get(current.CurrentValue)!; } if (value == null) @@ -92,6 +94,7 @@ protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writ protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { + Debug.Assert(Converter != null); JsonSerializer.WriteDictionary(Converter, Options, ref current, writer); } @@ -110,7 +113,7 @@ protected override void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonW } else { - value = (TConverter)current.CollectionEnumerator.Current; + value = (TConverter)current.CollectionEnumerator.Current!; } if (value == null) @@ -129,7 +132,7 @@ public override Type GetDictionaryConcreteType() return typeof(Dictionary); } - public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object value) + public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object? value) { if (writeStackFrame.CollectionEnumerator is IEnumerator> genericEnumerator) { @@ -139,7 +142,7 @@ public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStac else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - writeStackFrame.JsonPropertyInfo.DeclaredPropertyType, + writeStackFrame.JsonPropertyInfo!.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullableContravariant.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullableContravariant.cs index 1d68b6d52b11ec..80247d3226e005 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullableContravariant.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNotNullableContravariant.cs @@ -29,7 +29,8 @@ protected override void OnRead(ref ReadStack state, ref Utf8JsonReader reader) } else { - Set(state.Current.ReturnValue, (TDeclaredProperty)value); + Debug.Assert(Set != null); + Set(state.Current.ReturnValue, (TDeclaredProperty)value!); } return; @@ -64,10 +65,11 @@ protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writ TConverter value; if (IsPropertyPolicy) { - value = (TConverter)current.CurrentValue; + value = (TConverter)current.CurrentValue!; } else { + Debug.Assert(Get != null); value = (TConverter)Get(current.CurrentValue); } @@ -93,6 +95,7 @@ protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writ protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { + Debug.Assert(Converter != null); JsonSerializer.WriteDictionary(Converter, Options, ref current, writer); } @@ -110,7 +113,7 @@ protected override void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonW } else { - value = (TConverter)current.CollectionEnumerator.Current; + value = (TConverter)current.CollectionEnumerator.Current!; } if (value == null) @@ -129,7 +132,7 @@ public override Type GetDictionaryConcreteType() return typeof(Dictionary); } - public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object value) + public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object? value) { if (writeStackFrame.CollectionEnumerator is IEnumerator> genericEnumerator) { @@ -139,7 +142,7 @@ public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStac else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - writeStackFrame.JsonPropertyInfo.DeclaredPropertyType, + writeStackFrame.JsonPropertyInfo!.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNullable.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNullable.cs index 3605750fe5d38f..c5dbac440df0f7 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNullable.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonPropertyInfoNullable.cs @@ -33,6 +33,7 @@ protected override void OnRead(ref ReadStack state, ref Utf8JsonReader reader) } else { + Debug.Assert(Set != null); Set(state.Current.ReturnValue, value); } } @@ -58,6 +59,7 @@ protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writ } else { + Debug.Assert(Get != null); value = Get(current.CurrentValue); } @@ -85,7 +87,7 @@ protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonW { Debug.Assert(Converter != null && current.CollectionEnumerator != null); - string key = null; + string? key = null; TProperty? value = null; if (current.CollectionEnumerator is IEnumerator> enumerator) { @@ -94,7 +96,7 @@ protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonW } else { - if (((DictionaryEntry)current.CollectionEnumerator.Current).Key is string keyAsString) + if (((DictionaryEntry)current.CollectionEnumerator.Current!).Key is string keyAsString) { key = keyAsString; value = (TProperty?)((DictionaryEntry)current.CollectionEnumerator.Current).Value; @@ -102,7 +104,7 @@ protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonW else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - current.JsonPropertyInfo.DeclaredPropertyType, + current.JsonPropertyInfo!.DeclaredPropertyType, current.JsonPropertyInfo.ParentClassType, current.JsonPropertyInfo.PropertyInfo); } @@ -168,7 +170,7 @@ public override Type GetDictionaryConcreteType() return typeof(Dictionary); } - public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object value) + public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object? value) { if (writeStackFrame.CollectionEnumerator is IEnumerator> genericEnumerator) { @@ -178,7 +180,7 @@ public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStac else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - writeStackFrame.JsonPropertyInfo.DeclaredPropertyType, + writeStackFrame.JsonPropertyInfo!.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleArray.cs index 47e092d39a1f7b..854b9a2391ae1c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleArray.cs @@ -21,8 +21,8 @@ private static void HandleStartArray(JsonSerializerOptions options, ref ReadStac state.Current.Drain = true; return; } - - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; + Debug.Assert(state.Current.JsonClassInfo != null); + JsonPropertyInfo? jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null) { jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootProperty(options); @@ -37,7 +37,7 @@ private static void HandleStartArray(JsonSerializerOptions options, ref ReadStac if (state.Current.CollectionPropertyInitialized) { // An array nested in a dictionary or array, so push a new stack frame. - Type elementType = jsonPropertyInfo.ElementClassInfo.Type; + Type elementType = jsonPropertyInfo.ElementClassInfo!.Type; state.Push(); state.Current.Initialize(elementType, options); @@ -57,7 +57,7 @@ private static void HandleStartArray(JsonSerializerOptions options, ref ReadStac } // Set or replace the existing enumerable value. - object value = ReadStackFrame.CreateEnumerableValue(ref state); + object? value = ReadStackFrame.CreateEnumerableValue(ref state); // If value is not null, then we don't have a converter so apply the value. if (value != null) @@ -66,7 +66,7 @@ private static void HandleStartArray(JsonSerializerOptions options, ref ReadStac if (state.Current.ReturnValue != null) { - state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); + state.Current.JsonPropertyInfo!.SetValueAsObject(state.Current.ReturnValue, value); } else { @@ -88,21 +88,22 @@ private static bool HandleEndArray( return lastFrame; } - IEnumerable value = ReadStackFrame.GetEnumerableValue(ref state.Current); + IEnumerable? value = ReadStackFrame.GetEnumerableValue(ref state.Current); bool setPropertyDirectly = false; if (state.Current.TempEnumerableValues != null) { + Debug.Assert(state.Current.JsonPropertyInfo != null); // We have a converter; possibilities: // - Add value to current frame's current property or TempEnumerableValues. // - Add value to previous frame's current property or TempEnumerableValues. // - Set current property on current frame to value. // - Set current property on previous frame to value. // - Set ReturnValue if root frame and value is the actual return value. - JsonEnumerableConverter converter = state.Current.JsonPropertyInfo.EnumerableConverter; + JsonEnumerableConverter? converter = state.Current.JsonPropertyInfo.EnumerableConverter; Debug.Assert(converter != null); - value = converter.CreateFromList(ref state, (IList)value, options); + value = converter.CreateFromList(ref state, (IList)value!, options); state.Current.TempEnumerableValues = null; // Since we used a converter, we just processed an array or an immutable collection. This means we created a new enumerable object. @@ -146,11 +147,11 @@ private static bool HandleEndArray( // If this method is changed, also change ApplyValueToEnumerable. internal static void ApplyObjectToEnumerable( - object value, + object? value, ref ReadStack state, bool setPropertyDirectly = false) { - Debug.Assert(!state.Current.SkipProperty); + Debug.Assert(!state.Current.SkipProperty && state.Current.JsonPropertyInfo != null); if (state.Current.IsProcessingObject(ClassType.Enumerable)) { @@ -168,6 +169,7 @@ internal static void ApplyObjectToEnumerable( } else { + Debug.Assert(value != null); ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(value.GetType()); return; } @@ -191,7 +193,7 @@ internal static void ApplyObjectToEnumerable( { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; - object currentEnumerable = jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); + object? currentEnumerable = jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); if (currentEnumerable == null) { jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); @@ -209,7 +211,7 @@ internal static void ApplyObjectToEnumerable( } else if (state.Current.IsProcessingObject(ClassType.Dictionary) || (state.Current.IsProcessingProperty(ClassType.Dictionary) && !setPropertyDirectly)) { - string key = state.Current.KeyName; + string? key = state.Current.KeyName; Debug.Assert(!string.IsNullOrEmpty(key)); if (state.Current.TempDictionaryValues != null) @@ -220,7 +222,7 @@ internal static void ApplyObjectToEnumerable( { Debug.Assert(state.Current.ReturnValue != null); - object currentDictionary = state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); + object? currentDictionary = state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); if (currentDictionary is IDictionary dict) { @@ -229,6 +231,7 @@ internal static void ApplyObjectToEnumerable( } else { + Debug.Assert(currentDictionary != null); state.Current.JsonPropertyInfo.AddObjectToDictionary(currentDictionary, key, value); } } @@ -271,7 +274,7 @@ internal static void ApplyValueToEnumerable( JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; - object currentEnumerable = jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); + object? currentEnumerable = jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); if (currentEnumerable == null) { jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); @@ -284,7 +287,7 @@ internal static void ApplyValueToEnumerable( } else if (state.Current.IsProcessingDictionary()) { - string key = state.Current.KeyName; + string? key = state.Current.KeyName; Debug.Assert(!string.IsNullOrEmpty(key)); if (state.Current.TempDictionaryValues != null) @@ -293,9 +296,9 @@ internal static void ApplyValueToEnumerable( } else { - Debug.Assert(state.Current.ReturnValue != null); + Debug.Assert(state.Current.ReturnValue != null && state.Current.JsonPropertyInfo != null); - object currentDictionary = state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); + object? currentDictionary = state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); if (currentDictionary is IDictionary genericDict) { @@ -309,6 +312,7 @@ internal static void ApplyValueToEnumerable( } else { + Debug.Assert(currentDictionary != null); throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection(currentDictionary.GetType(), parentType: null, memberInfo: null); } } @@ -321,7 +325,7 @@ internal static void ApplyValueToEnumerable( } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void AddValueToEnumerable(ref ReadStack state, object target, TProperty value) + private static void AddValueToEnumerable(ref ReadStack state, object? target, TProperty value) { if (target is IList genericList) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleDictionary.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleDictionary.cs index a614ab0f4dd402..29a11f6ca075e5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleDictionary.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleDictionary.cs @@ -14,10 +14,10 @@ private static void HandleStartDictionary(JsonSerializerOptions options, ref Rea { Debug.Assert(!state.Current.IsProcessingEnumerable()); - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; + JsonPropertyInfo? jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null) { - jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootProperty(options); + jsonPropertyInfo = state.Current.JsonClassInfo!.CreateRootProperty(options); } Debug.Assert(jsonPropertyInfo != null); @@ -26,14 +26,14 @@ private static void HandleStartDictionary(JsonSerializerOptions options, ref Rea if (state.Current.CollectionPropertyInitialized) { state.Push(); - state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo; + state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo!; state.Current.InitializeJsonPropertyInfo(); JsonClassInfo classInfo = state.Current.JsonClassInfo; if (state.Current.IsProcessingDictionary()) { - object dictValue = ReadStackFrame.CreateDictionaryValue(ref state); + object? dictValue = ReadStackFrame.CreateDictionaryValue(ref state); // If value is not null, then we don't have a converter so apply the value. if (dictValue != null) @@ -63,13 +63,14 @@ private static void HandleStartDictionary(JsonSerializerOptions options, ref Rea state.Current.CollectionPropertyInitialized = true; - object value = ReadStackFrame.CreateDictionaryValue(ref state); + object? value = ReadStackFrame.CreateDictionaryValue(ref state); if (value != null) { state.Current.DetermineIfDictionaryCanBePopulated(value); if (state.Current.ReturnValue != null) { + Debug.Assert(state.Current.JsonPropertyInfo != null); state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); } else @@ -82,18 +83,21 @@ private static void HandleStartDictionary(JsonSerializerOptions options, ref Rea private static void HandleEndDictionary(JsonSerializerOptions options, ref ReadStack state) { - Debug.Assert(!state.Current.SkipProperty); + Debug.Assert(!state.Current.SkipProperty && state.Current.JsonPropertyInfo != null); if (state.Current.IsProcessingProperty(ClassType.Dictionary)) { if (state.Current.TempDictionaryValues != null) { - JsonDictionaryConverter converter = state.Current.JsonPropertyInfo.DictionaryConverter; + JsonDictionaryConverter? converter = state.Current.JsonPropertyInfo.DictionaryConverter; + Debug.Assert(converter != null); state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, converter.CreateFromDictionary(ref state, state.Current.TempDictionaryValues, options)); state.Current.EndProperty(); } else { + Debug.Assert(state.Current.JsonClassInfo != null); + // Handle special case of DataExtensionProperty where we just added a dictionary element to the extension property. // Since the JSON value is not a dictionary element (it's a normal property in JSON) a JsonTokenType.EndObject // encountered here is from the outer object so forward to HandleEndObject(). @@ -110,10 +114,11 @@ private static void HandleEndDictionary(JsonSerializerOptions options, ref ReadS } else { - object value; + object? value; if (state.Current.TempDictionaryValues != null) { - JsonDictionaryConverter converter = state.Current.JsonPropertyInfo.DictionaryConverter; + JsonDictionaryConverter? converter = state.Current.JsonPropertyInfo.DictionaryConverter; + Debug.Assert(converter != null); value = converter.CreateFromDictionary(ref state, state.Current.TempDictionaryValues, options); } else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleNull.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleNull.cs index c3878ed2c11ab6..07c81295facd33 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleNull.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleNull.cs @@ -19,7 +19,7 @@ private static bool HandleNull(JsonSerializerOptions options, ref Utf8JsonReader return false; } - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; + JsonPropertyInfo? jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null || (reader.CurrentDepth == 0 && jsonPropertyInfo.CanBeNull)) { @@ -28,8 +28,6 @@ private static bool HandleNull(JsonSerializerOptions options, ref Utf8JsonReader return true; } - Debug.Assert(jsonPropertyInfo != null); - if (state.Current.IsProcessingCollectionObject()) { AddNullToCollection(jsonPropertyInfo, ref reader, ref state); @@ -71,7 +69,7 @@ private static bool HandleNull(JsonSerializerOptions options, ref Utf8JsonReader if (!jsonPropertyInfo.IgnoreNullValues) { - state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value: null); + jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value: null); } return false; @@ -79,7 +77,7 @@ private static bool HandleNull(JsonSerializerOptions options, ref Utf8JsonReader private static void AddNullToCollection(JsonPropertyInfo jsonPropertyInfo, ref Utf8JsonReader reader, ref ReadStack state) { - JsonPropertyInfo elementPropertyInfo = jsonPropertyInfo.ElementClassInfo.PolicyProperty; + JsonPropertyInfo? elementPropertyInfo = jsonPropertyInfo.ElementClassInfo!.PolicyProperty; // if elementPropertyInfo == null then this element doesn't need a converter (an object). if (elementPropertyInfo?.CanBeNull == false) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleObject.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleObject.cs index 5c0aa80725c286..9d351b873ac87d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleObject.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleObject.cs @@ -22,7 +22,7 @@ private static void HandleStartObject(JsonSerializerOptions options, ref ReadSta if (!state.Current.CollectionPropertyInitialized) { // We have bad JSON: enumerable element appeared without preceding StartArray token. - ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonPropertyInfo.DeclaredPropertyType); + ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonPropertyInfo!.DeclaredPropertyType); } Type objType = state.Current.GetElementType(); @@ -39,11 +39,11 @@ private static void HandleStartObject(JsonSerializerOptions options, ref ReadSta state.Current.Initialize(objType, options); } - JsonClassInfo classInfo = state.Current.JsonClassInfo; + JsonClassInfo classInfo = state.Current.JsonClassInfo!; if (state.Current.IsProcessingObject(ClassType.Dictionary)) { - object value = ReadStackFrame.CreateDictionaryValue(ref state); + object? value = ReadStackFrame.CreateDictionaryValue(ref state); // If value is not null, then we don't have a converter so apply the value. if (value != null) @@ -72,6 +72,8 @@ private static void HandleStartObject(JsonSerializerOptions options, ref ReadSta private static void HandleEndObject(ref ReadStack state) { + Debug.Assert(state.Current.JsonClassInfo != null); + // Only allow dictionaries to be processed here if this is the DataExtensionProperty. Debug.Assert(!state.Current.IsProcessingDictionary() || state.Current.JsonClassInfo.DataExtensionProperty == state.Current.JsonPropertyInfo); @@ -81,7 +83,7 @@ private static void HandleEndObject(ref ReadStack state) state.Current.JsonClassInfo.UpdateSortedPropertyCache(ref state.Current); } - object value = state.Current.ReturnValue; + object? value = state.Current.ReturnValue; if (state.IsLastFrame) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs index b59abd393f35c6..aa9563e9429005 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs @@ -54,7 +54,7 @@ private static void HandlePropertyName( JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty(propertyName, ref state.Current); if (jsonPropertyInfo == JsonPropertyInfo.s_missingProperty) { - JsonPropertyInfo dataExtProperty = state.Current.JsonClassInfo.DataExtensionProperty; + JsonPropertyInfo? dataExtProperty = state.Current.JsonClassInfo!.DataExtensionProperty; if (dataExtProperty == null) { state.Current.JsonPropertyInfo = JsonPropertyInfo.s_missingProperty; @@ -108,7 +108,7 @@ private static void CreateDataExtensionProperty( Debug.Assert(jsonPropertyInfo != null); Debug.Assert(state.Current.ReturnValue != null); - IDictionary extensionData = (IDictionary)jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); + IDictionary? extensionData = (IDictionary?)jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue); if (extensionData == null) { // Create the appropriate dictionary type. We already verified the types. @@ -119,7 +119,8 @@ private static void CreateDataExtensionProperty( jsonPropertyInfo.DeclaredPropertyType.GetGenericArguments()[1].UnderlyingSystemType == typeof(object) || jsonPropertyInfo.DeclaredPropertyType.GetGenericArguments()[1].UnderlyingSystemType == typeof(JsonElement)); - extensionData = (IDictionary)jsonPropertyInfo.RuntimeClassInfo.CreateObject(); + Debug.Assert(jsonPropertyInfo.RuntimeClassInfo.CreateObject != null); + extensionData = (IDictionary?)jsonPropertyInfo.RuntimeClassInfo.CreateObject(); jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, extensionData); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleValue.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleValue.cs index 868a7c8091451d..38e25cbe6d02b9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleValue.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleValue.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; using System.Runtime.CompilerServices; namespace System.Text.Json @@ -17,7 +18,8 @@ private static void HandleValue(JsonTokenType tokenType, JsonSerializerOptions o return; } - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; + JsonPropertyInfo? jsonPropertyInfo = state.Current.JsonPropertyInfo; + Debug.Assert(state.Current.JsonClassInfo != null); if (jsonPropertyInfo == null) { jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootProperty(options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs index 8d41758722e819..350946775e7db8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs @@ -6,7 +6,7 @@ namespace System.Text.Json { public static partial class JsonSerializer { - private static object ReadCore( + private static object? ReadCore( Type returnType, JsonSerializerOptions options, ref Utf8JsonReader reader) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs index 7f9f13f1048d6f..93a4f5194b1833 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -19,9 +20,10 @@ public static partial class JsonSerializer /// is not compatible with the JSON, /// or when there is remaining data in the Stream. /// - public static TValue Deserialize(ReadOnlySpan utf8Json, JsonSerializerOptions options = null) + [return: MaybeNull] + public static TValue Deserialize(ReadOnlySpan utf8Json, JsonSerializerOptions? options = null) { - return (TValue)ParseCore(utf8Json, typeof(TValue), options); + return (TValue)ParseCore(utf8Json, typeof(TValue), options)!; } /// @@ -39,7 +41,7 @@ public static TValue Deserialize(ReadOnlySpan utf8Json, JsonSerial /// is not compatible with the JSON, /// or when there is remaining data in the Stream. /// - public static object Deserialize(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions options = null) + public static object? Deserialize(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions? options = null) { if (returnType == null) throw new ArgumentNullException(nameof(returnType)); @@ -47,7 +49,7 @@ public static object Deserialize(ReadOnlySpan utf8Json, Type returnType, J return ParseCore(utf8Json, returnType, options); } - private static object ParseCore(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions options) + private static object? ParseCore(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions? options) { if (options == null) { @@ -56,7 +58,7 @@ private static object ParseCore(ReadOnlySpan utf8Json, Type returnType, Js var readerState = new JsonReaderState(options.GetReaderOptions()); var reader = new Utf8JsonReader(utf8Json, isFinalBlock: true, readerState); - object result = ReadCore(returnType, options, ref reader); + object? result = ReadCore(returnType, options, ref reader); // The reader should have thrown if we have remaining bytes. Debug.Assert(reader.BytesConsumed == utf8Json.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs index 1dce5edc707851..67151485123c15 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -29,7 +30,7 @@ public static partial class JsonSerializer /// public static ValueTask DeserializeAsync( Stream utf8Json, - JsonSerializerOptions options = null, + JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { if (utf8Json == null) @@ -57,10 +58,10 @@ public static ValueTask DeserializeAsync( /// the is not compatible with the JSON, /// or when there is remaining data in the Stream. /// - public static ValueTask DeserializeAsync( + public static ValueTask DeserializeAsync( Stream utf8Json, Type returnType, - JsonSerializerOptions options = null, + JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { if (utf8Json == null) @@ -69,13 +70,13 @@ public static ValueTask DeserializeAsync( if (returnType == null) throw new ArgumentNullException(nameof(returnType)); - return ReadAsync(utf8Json, returnType, options, cancellationToken); + return ReadAsync(utf8Json, returnType, options, cancellationToken); } private static async ValueTask ReadAsync( Stream utf8Json, Type returnType, - JsonSerializerOptions options = null, + JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { if (options == null) @@ -197,7 +198,7 @@ private static async ValueTask ReadAsync( // The reader should have thrown if we have remaining bytes. Debug.Assert(bytesInBuffer == 0); - return (TValue)readStack.Current.ReturnValue; + return (TValue)readStack.Current.ReturnValue!; } private static void ReadCore( diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs index 3fed716a591eb2..f5379c748131cc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -26,9 +27,10 @@ public static partial class JsonSerializer /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static TValue Deserialize(string json, JsonSerializerOptions options = null) + [return: MaybeNull] + public static TValue Deserialize(string json, JsonSerializerOptions? options = null) { - return (TValue)Deserialize(json, typeof(TValue), options); + return (TValue)Deserialize(json, typeof(TValue), options)!; } /// @@ -49,7 +51,7 @@ public static TValue Deserialize(string json, JsonSerializerOptions opti /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static object Deserialize(string json, Type returnType, JsonSerializerOptions options = null) + public static object? Deserialize(string json, Type returnType, JsonSerializerOptions? options = null) { const long ArrayPoolMaxSizeBeforeUsingNormalAlloc = 1024 * 1024; @@ -68,8 +70,8 @@ public static object Deserialize(string json, Type returnType, JsonSerializerOpt options = JsonSerializerOptions.s_defaultOptions; } - object result; - byte[] tempArray = null; + object? result; + byte[]? tempArray = null; // For performance, avoid obtaining actual byte count unless memory usage is higher than the threshold. Span utf8 = json.Length <= (ArrayPoolMaxSizeBeforeUsingNormalAlloc / JsonConstants.MaxExpansionFactorWhileTranscoding) ? diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs index 7db0f4a921de61..fc84903a8c5728 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -47,9 +48,10 @@ public static partial class JsonSerializer /// Hence, , , are used while reading. /// /// - public static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions options = null) + [return: MaybeNull] + public static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions? options = null) { - return (TValue)ReadValueCore(ref reader, typeof(TValue), options); + return (TValue)ReadValueCore(ref reader, typeof(TValue), options)!; } /// @@ -93,7 +95,7 @@ public static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializ /// Hence, , , are used while reading. /// /// - public static object Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options = null) + public static object? Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions? options = null) { if (returnType == null) throw new ArgumentNullException(nameof(returnType)); @@ -101,7 +103,7 @@ public static object Deserialize(ref Utf8JsonReader reader, Type returnType, Jso return ReadValueCore(ref reader, returnType, options); } - private static object ReadValueCore(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options) + private static object? ReadValueCore(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions? options) { if (options == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs index d3f8ce83aa9ac8..0090ac206a8113 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.cs @@ -184,7 +184,7 @@ private static ReadOnlySpan GetUnescapedString(ReadOnlySpan utf8Sour { // The escaped name is always longer than the unescaped, so it is safe to use escaped name for the buffer length. int length = utf8Source.Length; - byte[] pooledName = null; + byte[]? pooledName = null; Span unescapedName = length <= JsonConstants.StackallocThreshold ? stackalloc byte[length] : diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs index 06064ca96286d0..0639fe0827979a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs @@ -12,7 +12,7 @@ public static partial class JsonSerializer /// A UTF-8 representation of the value. /// The value to convert. /// Options to control the conversion behavior. - public static byte[] SerializeToUtf8Bytes(TValue value, JsonSerializerOptions options = null) + public static byte[] SerializeToUtf8Bytes(TValue value, JsonSerializerOptions? options = null) { return WriteCoreBytes(value, typeof(TValue), options); } @@ -24,7 +24,7 @@ public static byte[] SerializeToUtf8Bytes(TValue value, JsonSerializerOp /// The value to convert. /// The type of the to convert. /// Options to control the conversion behavior. - public static byte[] SerializeToUtf8Bytes(object value, Type inputType, JsonSerializerOptions options = null) + public static byte[] SerializeToUtf8Bytes(object? value, Type inputType, JsonSerializerOptions? options = null) { VerifyValueAndType(value, inputType); return WriteCoreBytes(value, inputType, options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs index 22c1f2324ceea7..24bda6dadacdbb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleDictionary.cs @@ -17,16 +17,14 @@ private static bool HandleDictionary( Utf8JsonWriter writer, ref WriteStack state) { - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; + JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo!; if (state.Current.CollectionEnumerator == null) { - IEnumerable enumerable; - - enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); + IEnumerable? enumerable = (IEnumerable?)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { - if ((state.Current.JsonClassInfo.ClassType != ClassType.Object || // Write null dictionary values - !state.Current.JsonPropertyInfo.IgnoreNullValues) && // Ignore ClassType.Object properties if IgnoreNullValues is true + if ((state.Current.JsonClassInfo!.ClassType != ClassType.Object || // Write null dictionary values + !jsonPropertyInfo.IgnoreNullValues) && // Ignore ClassType.Object properties if IgnoreNullValues is true state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // Ignore null extension property (which is a dictionary) { // Write a null object or enumerable. @@ -59,8 +57,8 @@ private static bool HandleDictionary( Debug.Assert(state.Current.CollectionEnumerator.Current != null); bool obtainedValues = false; - string key = default; - object value = default; + string? key = default; + object? value = default; // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) @@ -72,7 +70,7 @@ private static bool HandleDictionary( if (elementClassInfo.ClassType == ClassType.Value) { - elementClassInfo.PolicyProperty.WriteDictionary(ref state, writer); + elementClassInfo.PolicyProperty!.WriteDictionary(ref state, writer); } else { @@ -83,7 +81,12 @@ private static bool HandleDictionary( if (options.DictionaryKeyPolicy != null && state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) { + Debug.Assert(key != null); key = options.DictionaryKeyPolicy.ConvertName(key); + if (key == null) + { + ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType()); + } } // An object or another enumerator requires a new stack frame. @@ -141,12 +144,12 @@ internal static void WriteDictionary( iDictionaryEnumerator.Key is string keyAsString) { key = keyAsString; - value = (TProperty)iDictionaryEnumerator.Value; + value = (TProperty)iDictionaryEnumerator.Value!; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( - current.JsonPropertyInfo.DeclaredPropertyType, + current.JsonPropertyInfo!.DeclaredPropertyType, current.JsonPropertyInfo.ParentClassType, current.JsonPropertyInfo.PropertyInfo); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleEnumerable.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleEnumerable.cs index 9ef8bc6a485a5b..2fb2973140f3a9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleEnumerable.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleEnumerable.cs @@ -15,16 +15,16 @@ private static bool HandleEnumerable( Utf8JsonWriter writer, ref WriteStack state) { - Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable); + Debug.Assert(state.Current.JsonPropertyInfo!.ClassType == ClassType.Enumerable); if (state.Current.CollectionEnumerator == null) { - IEnumerable enumerable = (IEnumerable)state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); + IEnumerable? enumerable = (IEnumerable?)state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { // If applicable, we only want to ignore object properties. - if (state.Current.JsonClassInfo.ClassType != ClassType.Object || + if (state.Current.JsonClassInfo!.ClassType != ClassType.Object || !state.Current.JsonPropertyInfo.IgnoreNullValues) { // Write a null object or enumerable. @@ -49,13 +49,13 @@ private static bool HandleEnumerable( // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { - object currentValue = state.Current.CollectionEnumerator.Current; + object? currentValue = state.Current.CollectionEnumerator.Current; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { - elementClassInfo.PolicyProperty.WriteEnumerable(ref state, writer); + elementClassInfo.PolicyProperty!.WriteEnumerable(ref state, writer); } else if (state.Current.CollectionEnumerator.Current == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleObject.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleObject.cs index 540c86eadb017d..62b06e776c284a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleObject.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.HandleObject.cs @@ -41,9 +41,9 @@ private static bool WriteObject( if (state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Finished) { // If ClassType.Unknown at this point, we are typeof(object) which should not have any properties. - Debug.Assert(state.Current.JsonClassInfo.ClassType != ClassType.Unknown); + Debug.Assert(state.Current.JsonClassInfo!.ClassType != ClassType.Unknown); - JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.PropertyCacheArray[state.Current.PropertyEnumeratorIndex - 1]; + JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.PropertyCacheArray![state.Current.PropertyEnumeratorIndex - 1]; HandleObject(jsonPropertyInfo, options, writer, ref state); return false; @@ -72,7 +72,7 @@ private static void HandleObject( ref WriteStack state) { Debug.Assert( - state.Current.JsonClassInfo.ClassType == ClassType.Object || + state.Current.JsonClassInfo!.ClassType == ClassType.Object || state.Current.JsonClassInfo.ClassType == ClassType.Unknown); if (!jsonPropertyInfo.ShouldSerialize) @@ -82,7 +82,7 @@ private static void HandleObject( } bool obtainedValue = false; - object currentValue = null; + object? currentValue = null; // Check for polymorphism. if (jsonPropertyInfo.ClassType == ClassType.Unknown) @@ -104,7 +104,7 @@ private static void HandleObject( // A property that returns an enumerator keeps the same stack frame. if (jsonPropertyInfo.ClassType == ClassType.Enumerable) { - bool endOfEnumerable = HandleEnumerable(jsonPropertyInfo.ElementClassInfo, options, writer, ref state); + bool endOfEnumerable = HandleEnumerable(jsonPropertyInfo.ElementClassInfo!, options, writer, ref state); if (endOfEnumerable) { state.Current.MoveToNextProperty = true; @@ -116,7 +116,7 @@ private static void HandleObject( // A property that returns a dictionary keeps the same stack frame. if (jsonPropertyInfo.ClassType == ClassType.Dictionary) { - bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo, options, writer, ref state); + bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo!, options, writer, ref state); if (endOfEnumerable) { state.Current.MoveToNextProperty = true; @@ -147,6 +147,7 @@ private static void HandleObject( { if (!jsonPropertyInfo.IgnoreNullValues) { + Debug.Assert(jsonPropertyInfo.EscapedName != null); writer.WriteNull(jsonPropertyInfo.EscapedName.Value); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs index 0413a3f206f650..56d4be68b924f5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs @@ -8,7 +8,7 @@ namespace System.Text.Json { public static partial class JsonSerializer { - private static void GetRuntimeClassInfo(object value, ref JsonClassInfo jsonClassInfo, JsonSerializerOptions options) + private static void GetRuntimeClassInfo(object? value, ref JsonClassInfo jsonClassInfo, JsonSerializerOptions options) { if (value != null) { @@ -22,7 +22,7 @@ private static void GetRuntimeClassInfo(object value, ref JsonClassInfo jsonClas } } - private static void GetRuntimePropertyInfo(object value, JsonClassInfo jsonClassInfo, ref JsonPropertyInfo jsonPropertyInfo, JsonSerializerOptions options) + private static void GetRuntimePropertyInfo(object? value, JsonClassInfo jsonClassInfo, ref JsonPropertyInfo jsonPropertyInfo, JsonSerializerOptions options) { if (value != null) { @@ -36,14 +36,11 @@ private static void GetRuntimePropertyInfo(object value, JsonClassInfo jsonClass } } - private static void VerifyValueAndType(object value, Type type) + private static void VerifyValueAndType(object? value, Type type) { if (type == null) { - if (value != null) - { - throw new ArgumentNullException(nameof(type)); - } + throw new ArgumentNullException(nameof(type)); } else if (value != null) { @@ -54,7 +51,7 @@ private static void VerifyValueAndType(object value, Type type) } } - private static byte[] WriteCoreBytes(object value, Type type, JsonSerializerOptions options) + private static byte[] WriteCoreBytes(object? value, Type type, JsonSerializerOptions? options) { if (options == null) { @@ -72,7 +69,7 @@ private static byte[] WriteCoreBytes(object value, Type type, JsonSerializerOpti return result; } - private static string WriteCoreString(object value, Type type, JsonSerializerOptions options) + private static string WriteCoreString(object? value, Type type, JsonSerializerOptions? options) { if (options == null) { @@ -90,7 +87,7 @@ private static string WriteCoreString(object value, Type type, JsonSerializerOpt return result; } - private static void WriteValueCore(Utf8JsonWriter writer, object value, Type type, JsonSerializerOptions options) + private static void WriteValueCore(Utf8JsonWriter writer, object? value, Type type, JsonSerializerOptions? options) { if (options == null) { @@ -105,7 +102,7 @@ private static void WriteValueCore(Utf8JsonWriter writer, object value, Type typ WriteCore(writer, value, type, options); } - private static void WriteCore(PooledByteBufferWriter output, object value, Type type, JsonSerializerOptions options) + private static void WriteCore(PooledByteBufferWriter output, object? value, Type type, JsonSerializerOptions options) { using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) { @@ -113,7 +110,7 @@ private static void WriteCore(PooledByteBufferWriter output, object value, Type } } - private static void WriteCore(Utf8JsonWriter writer, object value, Type type, JsonSerializerOptions options) + private static void WriteCore(Utf8JsonWriter writer, object? value, Type type, JsonSerializerOptions options) { Debug.Assert(type != null || value == null); Debug.Assert(writer != null); @@ -131,6 +128,7 @@ private static void WriteCore(Utf8JsonWriter writer, object value, Type type, Js } WriteStack state = default; + Debug.Assert(type != null); state.Current.Initialize(type, options); state.Current.CurrentValue = value; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs index ca3bd482296a98..d7c1b24500cdb9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs @@ -18,7 +18,7 @@ public static partial class JsonSerializer /// The value to convert. /// Options to control the conversion behavior. /// The which may be used to cancel the write operation. - public static Task SerializeAsync(Stream utf8Json, TValue value, JsonSerializerOptions options = null, CancellationToken cancellationToken = default) + public static Task SerializeAsync(Stream utf8Json, TValue value, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { return WriteAsyncCore(utf8Json, value, typeof(TValue), options, cancellationToken); } @@ -32,7 +32,7 @@ public static Task SerializeAsync(Stream utf8Json, TValue value, JsonSer /// The type of the to convert. /// Options to control the conversion behavior. /// The which may be used to cancel the write operation. - public static Task SerializeAsync(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options = null, CancellationToken cancellationToken = default) + public static Task SerializeAsync(Stream utf8Json, object? value, Type inputType, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { if (utf8Json == null) throw new ArgumentNullException(nameof(utf8Json)); @@ -42,7 +42,7 @@ public static Task SerializeAsync(Stream utf8Json, object value, Type inputType, return WriteAsyncCore(utf8Json, value, inputType, options, cancellationToken); } - private static async Task WriteAsyncCore(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken) + private static async Task WriteAsyncCore(Stream utf8Json, object? value, Type inputType, JsonSerializerOptions? options, CancellationToken cancellationToken) { if (options == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs index 8937e2c9ec8642..6464b1c6b7b2d4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs @@ -16,7 +16,7 @@ public static partial class JsonSerializer /// encoding since the implementation internally uses UTF-8. See also /// and . /// - public static string Serialize(TValue value, JsonSerializerOptions options = null) + public static string Serialize(TValue value, JsonSerializerOptions? options = null) { return WriteCoreString(value, typeof(TValue), options); } @@ -32,7 +32,7 @@ public static string Serialize(TValue value, JsonSerializerOptions optio /// encoding since the implementation internally uses UTF-8. See also /// and . /// - public static string Serialize(object value, Type inputType, JsonSerializerOptions options = null) + public static string Serialize(object? value, Type inputType, JsonSerializerOptions? options = null) { VerifyValueAndType(value, inputType); return WriteCoreString(value, inputType, options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs index 8e285557f37ea1..aa420f900d468a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs @@ -15,7 +15,7 @@ public static partial class JsonSerializer /// /// is null. /// - public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSerializerOptions options = null) + public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSerializerOptions? options = null) { WriteValueCore(writer, value, typeof(TValue), options); } @@ -30,7 +30,7 @@ public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSe /// /// is null. /// - public static void Serialize(Utf8JsonWriter writer, object value, Type inputType, JsonSerializerOptions options = null) + public static void Serialize(Utf8JsonWriter writer, object? value, Type inputType, JsonSerializerOptions? options = null) { VerifyValueAndType(value, inputType); WriteValueCore(writer, value, inputType, options); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.cs index 5f25813631d5df..ce6e11fa7eae08 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.cs @@ -25,18 +25,18 @@ private static bool Write( { do { - switch (state.Current.JsonClassInfo.ClassType) + switch (state.Current.JsonClassInfo!.ClassType) { case ClassType.Enumerable: - finishedSerializing = HandleEnumerable(state.Current.JsonClassInfo.ElementClassInfo, options, writer, ref state); + finishedSerializing = HandleEnumerable(state.Current.JsonClassInfo.ElementClassInfo!, options, writer, ref state); break; case ClassType.Value: - Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Value); + Debug.Assert(state.Current.JsonPropertyInfo!.ClassType == ClassType.Value); state.Current.JsonPropertyInfo.Write(ref state, writer); finishedSerializing = true; break; case ClassType.Dictionary: - finishedSerializing = HandleDictionary(state.Current.JsonClassInfo.ElementClassInfo, options, writer, ref state); + finishedSerializing = HandleDictionary(state.Current.JsonClassInfo.ElementClassInfo!, options, writer, ref state); break; default: Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Object || diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs index 9be3015f510dc6..161c1345c8af7b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs @@ -23,7 +23,7 @@ public sealed partial class JsonSerializerOptions private static readonly List s_defaultFactoryConverters = GetDefaultConverters(); // The cached converters (custom or built-in). - private readonly ConcurrentDictionary _converters = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _converters = new ConcurrentDictionary(); private static Dictionary GetDefaultSimpleConverters() { @@ -32,7 +32,7 @@ private static Dictionary GetDefaultSimpleConverters() // Use a dictionary for simple converters. foreach (JsonConverter converter in DefaultSimpleConverters) { - converters.Add(converter.TypeToConvert, converter); + converters.Add(converter.TypeToConvert!, converter); } Debug.Assert(NumberOfSimpleConverters == converters.Count); @@ -65,14 +65,14 @@ private static List GetDefaultConverters() /// public IList Converters { get; } - internal JsonConverter DetermineConverterForProperty(Type parentClassType, Type runtimePropertyType, PropertyInfo propertyInfo) + internal JsonConverter? DetermineConverterForProperty(Type parentClassType, Type runtimePropertyType, PropertyInfo? propertyInfo) { - JsonConverter converter = null; + JsonConverter? converter = null; // Priority 1: attempt to get converter from JsonConverterAttribute on property. if (propertyInfo != null) { - JsonConverterAttribute converterAttribute = (JsonConverterAttribute) + JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?) GetAttributeThatCanHaveMultiple(parentClassType, typeof(JsonConverterAttribute), propertyInfo); if (converterAttribute != null) @@ -101,9 +101,9 @@ internal JsonConverter DetermineConverterForProperty(Type parentClassType, Type /// /// The first converter that supports the given type, or null if there is no converter. /// - public JsonConverter GetConverter(Type typeToConvert) + public JsonConverter? GetConverter(Type typeToConvert) { - if (_converters.TryGetValue(typeToConvert, out JsonConverter converter)) + if (_converters.TryGetValue(typeToConvert, out JsonConverter? converter)) { return converter; } @@ -122,7 +122,7 @@ public JsonConverter GetConverter(Type typeToConvert) // Priority 3: Attempt to get converter from [JsonConverter] on the type being converted. if (converter == null) { - JsonConverterAttribute converterAttribute = (JsonConverterAttribute) + JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?) GetAttributeThatCanHaveMultiple(typeToConvert, typeof(JsonConverterAttribute)); if (converterAttribute != null) @@ -134,7 +134,7 @@ public JsonConverter GetConverter(Type typeToConvert) // Priority 4: Attempt to get built-in converter. if (converter == null) { - if (s_defaultSimpleConverters.TryGetValue(typeToConvert, out JsonConverter foundConverter)) + if (s_defaultSimpleConverters.TryGetValue(typeToConvert, out JsonConverter? foundConverter)) { converter = foundConverter; } @@ -163,7 +163,7 @@ public JsonConverter GetConverter(Type typeToConvert) if (converter != null) { - Type converterTypeToConvert = converter.TypeToConvert; + Type converterTypeToConvert = converter.TypeToConvert!; if (!converterTypeToConvert.IsAssignableFrom(typeToConvert) && !typeToConvert.IsAssignableFrom(converterTypeToConvert)) @@ -189,11 +189,11 @@ internal bool HasConverter(Type typeToConvert) return GetConverter(typeToConvert) != null; } - private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converterAttribute, Type typeToConvert, Type classTypeAttributeIsOn, PropertyInfo propertyInfo) + private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converterAttribute, Type typeToConvert, Type classTypeAttributeIsOn, PropertyInfo? propertyInfo) { - JsonConverter converter; + JsonConverter? converter; - Type type = converterAttribute.ConverterType; + Type? type = converterAttribute.ConverterType; if (type == null) { // Allow the attribute to create the converter. @@ -205,15 +205,16 @@ private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converter } else { - ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes); - if (!typeof(JsonConverter).IsAssignableFrom(type) || !ctor.IsPublic) + ConstructorInfo? ctor = type.GetConstructor(Type.EmptyTypes); + if (!typeof(JsonConverter).IsAssignableFrom(type) || ctor == null || !ctor.IsPublic) { ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(classTypeAttributeIsOn, propertyInfo); } - converter = (JsonConverter)Activator.CreateInstance(type); + converter = (JsonConverter)Activator.CreateInstance(type)!; } + Debug.Assert(converter != null); if (!converter.CanConvert(typeToConvert)) { ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(classTypeAttributeIsOn, propertyInfo, typeToConvert); @@ -222,19 +223,19 @@ private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converter return converter; } - private static Attribute GetAttributeThatCanHaveMultiple(Type classType, Type attributeType, PropertyInfo propertyInfo) + private static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType, PropertyInfo propertyInfo) { - object[] attributes = propertyInfo?.GetCustomAttributes(attributeType, inherit: false); + object[] attributes = propertyInfo.GetCustomAttributes(attributeType, inherit: false); return GetAttributeThatCanHaveMultiple(attributeType, classType, propertyInfo, attributes); } - private static Attribute GetAttributeThatCanHaveMultiple(Type classType, Type attributeType) + private static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType) { object[] attributes = classType.GetCustomAttributes(attributeType, inherit: false); return GetAttributeThatCanHaveMultiple(attributeType, classType, null, attributes); } - private static Attribute GetAttributeThatCanHaveMultiple(Type attributeType, Type classType, PropertyInfo propertyInfo, object[] attributes) + private static Attribute? GetAttributeThatCanHaveMultiple(Type attributeType, Type classType, PropertyInfo? propertyInfo, object[] attributes) { if (attributes.Length == 0) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index c4f78503c7538d..edbde98fbe3921 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Text.Json.Serialization; using System.Text.Encodings.Web; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -20,11 +21,11 @@ public sealed partial class JsonSerializerOptions private readonly ConcurrentDictionary _classes = new ConcurrentDictionary(); private static readonly ConcurrentDictionary s_createRangeDelegates = new ConcurrentDictionary(); - private MemberAccessor _memberAccessorStrategy; - private JsonNamingPolicy _dictionayKeyPolicy; - private JsonNamingPolicy _jsonPropertyNamingPolicy; + private MemberAccessor? _memberAccessorStrategy; + private JsonNamingPolicy? _dictionayKeyPolicy; + private JsonNamingPolicy? _jsonPropertyNamingPolicy; private JsonCommentHandling _readCommentHandling; - private JavaScriptEncoder _encoder; + private JavaScriptEncoder? _encoder; private int _defaultBufferSize = BufferSizeDefault; private int _maxDepth; private bool _allowTrailingCommas; @@ -95,7 +96,7 @@ public int DefaultBufferSize /// /// The encoder to use when escaping strings, or to use the default encoder. /// - public JavaScriptEncoder Encoder + public JavaScriptEncoder? Encoder { get { @@ -116,7 +117,7 @@ public JavaScriptEncoder Encoder /// This property can be set to to specify a camel-casing policy. /// It is not used when deserializing. /// - public JsonNamingPolicy DictionaryKeyPolicy + public JsonNamingPolicy? DictionaryKeyPolicy { get { @@ -214,7 +215,7 @@ public int MaxDepth /// The policy is not used for properties that have a applied. /// This property can be set to to specify a camel-casing policy. /// - public JsonNamingPolicy PropertyNamingPolicy + public JsonNamingPolicy? PropertyNamingPolicy { get { @@ -319,7 +320,7 @@ internal JsonClassInfo GetOrAddClass(Type classType) _haveTypesBeenCreated = true; // todo: for performance and reduced instances, consider using the converters and JsonClassInfo from s_defaultOptions by cloning (or reference directly if no changes). - if (!_classes.TryGetValue(classType, out JsonClassInfo result)) + if (!_classes.TryGetValue(classType, out JsonClassInfo? result)) { result = _classes.GetOrAdd(classType, new JsonClassInfo(classType, this)); } @@ -354,7 +355,7 @@ internal bool CreateRangeDelegatesContainsKey(string key) return s_createRangeDelegates.ContainsKey(key); } - internal bool TryGetCreateRangeDelegate(string delegateKey, out ImmutableCollectionCreator createRangeDelegate) + internal bool TryGetCreateRangeDelegate(string delegateKey, [NotNullWhen(true)] out ImmutableCollectionCreator? createRangeDelegate) { return s_createRangeDelegates.TryGetValue(delegateKey, out createRangeDelegate) && createRangeDelegate != null; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs index 9daddb0b63b41d..056432c0259cd2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs @@ -16,7 +16,7 @@ namespace System.Text.Json.Serialization /// public sealed class JsonStringEnumConverter : JsonConverterFactory { - private readonly JsonNamingPolicy _namingPolicy; + private readonly JsonNamingPolicy? _namingPolicy; private readonly EnumConverterOptions _converterOptions; /// @@ -39,7 +39,7 @@ public JsonStringEnumConverter() /// True to allow undefined enum values. When true, if an enum value isn't /// defined it will output as a number rather than a string. /// - public JsonStringEnumConverter(JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true) + public JsonStringEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { _namingPolicy = namingPolicy; _converterOptions = allowIntegerValues @@ -63,8 +63,8 @@ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializer typeof(JsonConverterEnum<>).MakeGenericType(typeToConvert), BindingFlags.Instance | BindingFlags.Public, binder: null, - new object[] { _converterOptions, _namingPolicy }, - culture: null); + new object?[] { _converterOptions, _namingPolicy }, + culture: null)!; return converter; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/MemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/MemberAccessor.cs index c3b31ad300b49d..1f34061f1f0021 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/MemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/MemberAccessor.cs @@ -9,7 +9,7 @@ namespace System.Text.Json { internal abstract class MemberAccessor { - public abstract JsonClassInfo.ConstructorDelegate CreateConstructor(Type classType); + public abstract JsonClassInfo.ConstructorDelegate? CreateConstructor(Type classType); public abstract Action CreateAddDelegate(MethodInfo addMethod, object target); @@ -21,11 +21,6 @@ protected MethodInfo ImmutableCollectionCreateRangeMethod(Type constructingType, { MethodInfo createRangeMethod = FindImmutableCreateRangeMethod(constructingType); - if (createRangeMethod == null) - { - return null; - } - return createRangeMethod.MakeGenericMethod(elementType); } @@ -33,11 +28,6 @@ protected MethodInfo ImmutableDictionaryCreateRangeMethod(Type constructingType, { MethodInfo createRangeMethod = FindImmutableCreateRangeMethod(constructingType); - if (createRangeMethod == null) - { - return null; - } - return createRangeMethod.MakeGenericMethod(typeof(string), elementType); } @@ -57,11 +47,11 @@ private MethodInfo FindImmutableCreateRangeMethod(Type constructingType) // a CreateRange method. `null` being returned here will cause a JsonException to be // thrown when the desired CreateRange delegate is about to be invoked. Debug.Fail("Could not create the appropriate CreateRange method."); - return null; + return null!; } - public abstract Func CreatePropertyGetter(PropertyInfo propertyInfo); + public abstract Func CreatePropertyGetter(PropertyInfo propertyInfo); - public abstract Action CreatePropertySetter(PropertyInfo propertyInfo); + public abstract Action CreatePropertySetter(PropertyInfo propertyInfo); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PooledByteBufferWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PooledByteBufferWriter.cs index 585094523e682f..6f6a7ae89d5710 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PooledByteBufferWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/PooledByteBufferWriter.cs @@ -86,7 +86,7 @@ public void Dispose() ClearHelper(); ArrayPool.Shared.Return(_rentedBuffer); - _rentedBuffer = null; + _rentedBuffer = null!; } public void Advance(int count) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs index f63a6c6355b4ca..1063ffd7d51773 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs @@ -70,7 +70,7 @@ public string JsonPath() private void AppendStackFrame(StringBuilder sb, in ReadStackFrame frame) { // Append the property name. - string propertyName = GetPropertyName(frame); + string? propertyName = GetPropertyName(frame); AppendPropertyName(sb, propertyName); if (frame.JsonClassInfo != null) @@ -82,11 +82,11 @@ private void AppendStackFrame(StringBuilder sb, in ReadStackFrame frame) } else if (frame.IsProcessingEnumerable()) { - IList list = frame.TempEnumerableValues; + IList? list = frame.TempEnumerableValues; if (list == null && frame.ReturnValue != null) { - list = (IList)frame.JsonPropertyInfo?.GetValueAsObject(frame.ReturnValue); + list = (IList?)frame.JsonPropertyInfo?.GetValueAsObject(frame.ReturnValue); } if (list != null) { @@ -98,7 +98,7 @@ private void AppendStackFrame(StringBuilder sb, in ReadStackFrame frame) } } - private void AppendPropertyName(StringBuilder sb, string propertyName) + private void AppendPropertyName(StringBuilder sb, string? propertyName) { if (propertyName != null) { @@ -116,17 +116,17 @@ private void AppendPropertyName(StringBuilder sb, string propertyName) } } - private string GetPropertyName(in ReadStackFrame frame) + private string? GetPropertyName(in ReadStackFrame frame) { // Attempt to get the JSON property name from the frame. - byte[] utf8PropertyName = frame.JsonPropertyName; + byte[]? utf8PropertyName = frame.JsonPropertyName; if (utf8PropertyName == null) { // Attempt to get the JSON property name from the JsonPropertyInfo. utf8PropertyName = frame.JsonPropertyInfo?.JsonPropertyName; } - string propertyName; + string? propertyName; if (utf8PropertyName != null) { propertyName = JsonHelpers.Utf8GetString(utf8PropertyName); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs index f9d064cd3b8f4e..76844bd608ea24 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStackFrame.cs @@ -13,23 +13,23 @@ namespace System.Text.Json internal struct ReadStackFrame { // The object (POCO or IEnumerable) that is being populated - public object ReturnValue; - public JsonClassInfo JsonClassInfo; + public object? ReturnValue; + public JsonClassInfo? JsonClassInfo; // Support Dictionary keys. - public string KeyName; + public string? KeyName; // Support JSON Path on exceptions. - public byte[] JsonPropertyName; + public byte[]? JsonPropertyName; // Current property values. - public JsonPropertyInfo JsonPropertyInfo; + public JsonPropertyInfo? JsonPropertyInfo; // Delegate used to add elements to the current property. - public object AddObjectToEnumerable; + public object? AddObjectToEnumerable; // Support System.Array and other types that don't implement IList. - public IList TempEnumerableValues; + public IList? TempEnumerableValues; // Has an array or dictionary property been initialized. public bool CollectionPropertyInitialized; @@ -40,11 +40,11 @@ internal struct ReadStackFrame // Support IDictionary constructible types, i.e. types that we // support by passing and IDictionary to their constructors: // immutable dictionaries, Hashtable, SortedList - public IDictionary TempDictionaryValues; + public IDictionary? TempDictionaryValues; // For performance, we order the properties by the first deserialize and PropertyIndex helps find the right slot quicker. public int PropertyIndex; - public List PropertyRefCache; + public List? PropertyRefCache; /// /// Is the current object an Enumerable or Dictionary. @@ -94,6 +94,7 @@ public bool IsProcessingEnumerable() /// public bool IsProcessingObject(ClassType classTypes) { + Debug.Assert(JsonClassInfo != null); return (JsonClassInfo.ClassType & classTypes) != 0; } @@ -124,10 +125,12 @@ public bool IsProcessingValue() if (CollectionPropertyInitialized) { + Debug.Assert(JsonPropertyInfo != null && JsonPropertyInfo.ElementClassInfo != null); classType = JsonPropertyInfo.ElementClassInfo.ClassType; } else if (JsonPropertyInfo == null) { + Debug.Assert(JsonClassInfo != null); classType = JsonClassInfo.ClassType; } else @@ -152,7 +155,7 @@ public void InitializeJsonPropertyInfo() { if (IsProcessingObject(ClassType.Value | ClassType.Enumerable | ClassType.Dictionary)) { - JsonPropertyInfo = JsonClassInfo.PolicyProperty; + JsonPropertyInfo = JsonClassInfo!.PolicyProperty; } } @@ -182,18 +185,19 @@ public void EndProperty() KeyName = null; } - public static object CreateEnumerableValue(ref ReadStack state) + public static object? CreateEnumerableValue(ref ReadStack state) { + Debug.Assert(state.Current.JsonPropertyInfo != null); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; // If the property has an EnumerableConverter, then we use tempEnumerableValues. if (jsonPropertyInfo.EnumerableConverter != null) { IList converterList; - JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo; + JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo!; if (elementClassInfo.ClassType == ClassType.Value) { - converterList = elementClassInfo.PolicyProperty.CreateConverterList(); + converterList = elementClassInfo.PolicyProperty!.CreateConverterList(); } else { @@ -221,18 +225,19 @@ public static object CreateEnumerableValue(ref ReadStack state) return runtimeClassInfo.CreateObject(); } - public static object CreateDictionaryValue(ref ReadStack state) + public static object? CreateDictionaryValue(ref ReadStack state) { + Debug.Assert(state.Current.JsonPropertyInfo != null); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; // If the property has a DictionaryConverter, then we use tempDictionaryValues. if (jsonPropertyInfo.DictionaryConverter != null) { IDictionary converterDictionary; - JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo; + JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo!; if (elementClassInfo.ClassType == ClassType.Value) { - converterDictionary = elementClassInfo.PolicyProperty.CreateConverterDictionary(); + converterDictionary = elementClassInfo.PolicyProperty!.CreateConverterDictionary(); } else { @@ -262,20 +267,21 @@ public static object CreateDictionaryValue(ref ReadStack state) public Type GetElementType() { + Debug.Assert(JsonPropertyInfo != null); if (IsProcessingCollectionProperty()) { - return JsonPropertyInfo.ElementClassInfo.Type; + return JsonPropertyInfo.ElementClassInfo!.Type; } if (IsProcessingCollectionObject()) { - return JsonClassInfo.ElementClassInfo.Type; + return JsonClassInfo!.ElementClassInfo!.Type; } return JsonPropertyInfo.RuntimePropertyType; } - public static IEnumerable GetEnumerableValue(ref ReadStackFrame current) + public static IEnumerable? GetEnumerableValue(ref ReadStackFrame current) { if (current.IsProcessingObject(ClassType.Enumerable)) { @@ -291,11 +297,11 @@ public static IEnumerable GetEnumerableValue(ref ReadStackFrame current) public void DetermineEnumerablePopulationStrategy(object targetEnumerable) { - Debug.Assert(JsonPropertyInfo.ClassType == ClassType.Enumerable); + Debug.Assert(JsonPropertyInfo!.ClassType == ClassType.Enumerable); if (JsonPropertyInfo.RuntimeClassInfo.AddItemToObject != null) { - if (!JsonPropertyInfo.TryCreateEnumerableAddMethod(targetEnumerable, out object addMethodDelegate)) + if (!JsonPropertyInfo.TryCreateEnumerableAddMethod(targetEnumerable, out object? addMethodDelegate)) { // No "add" method for this collection, hence, not supported for deserialization. throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( @@ -328,7 +334,7 @@ public void DetermineEnumerablePopulationStrategy(object targetEnumerable) public void DetermineIfDictionaryCanBePopulated(object targetDictionary) { - Debug.Assert(JsonPropertyInfo.ClassType == ClassType.Dictionary); + Debug.Assert(JsonPropertyInfo!.ClassType == ClassType.Dictionary); if (!JsonPropertyInfo.CanPopulateDictionary(targetDictionary)) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs index 323174d6466aad..cd5135ea7959c6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionEmitMemberAccessor.cs @@ -12,10 +12,10 @@ namespace System.Text.Json { internal sealed class ReflectionEmitMemberAccessor : MemberAccessor { - public override JsonClassInfo.ConstructorDelegate CreateConstructor(Type type) + public override JsonClassInfo.ConstructorDelegate? CreateConstructor(Type type) { Debug.Assert(type != null); - ConstructorInfo realMethod = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, modifiers: null); + ConstructorInfo? realMethod = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, modifiers: null); if (type.IsAbstract) { @@ -66,14 +66,9 @@ public override ImmutableCollectionCreator ImmutableCollectionCreateRange(Type c { MethodInfo createRange = ImmutableCollectionCreateRangeMethod(constructingType, elementType); - if (createRange == null) - { - return null; - } - Type creatorType = typeof(ImmutableEnumerableCreator<,>).MakeGenericType(elementType, collectionType); - ConstructorInfo realMethod = creatorType.GetConstructor( + ConstructorInfo? realMethod = creatorType.GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, @@ -95,8 +90,9 @@ public override ImmutableCollectionCreator ImmutableCollectionCreateRange(Type c JsonClassInfo.ConstructorDelegate constructor = (JsonClassInfo.ConstructorDelegate)dynamicMethod.CreateDelegate( typeof(JsonClassInfo.ConstructorDelegate)); - ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor(); + ImmutableCollectionCreator? creator = (ImmutableCollectionCreator?)constructor(); + Debug.Assert(creator != null); creator.RegisterCreatorDelegateFromMethod(createRange); return creator; } @@ -114,14 +110,9 @@ public override ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type c MethodInfo createRange = ImmutableDictionaryCreateRangeMethod(constructingType, elementType); - if (createRange == null) - { - return null; - } - Type creatorType = typeof(ImmutableDictionaryCreator<,>).MakeGenericType(elementType, collectionType); - ConstructorInfo realMethod = creatorType.GetConstructor( + ConstructorInfo? realMethod = creatorType.GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, @@ -143,20 +134,22 @@ public override ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type c JsonClassInfo.ConstructorDelegate constructor = (JsonClassInfo.ConstructorDelegate)dynamicMethod.CreateDelegate( typeof(JsonClassInfo.ConstructorDelegate)); - ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor(); + ImmutableCollectionCreator? creator = (ImmutableCollectionCreator?)constructor(); + Debug.Assert(creator != null); creator.RegisterCreatorDelegateFromMethod(createRange); return creator; } - public override Func CreatePropertyGetter(PropertyInfo propertyInfo) => - (Func)CreatePropertyGetter(propertyInfo, typeof(TClass)); + public override Func CreatePropertyGetter(PropertyInfo propertyInfo) => + (Func)CreatePropertyGetter(propertyInfo, typeof(TClass)); private static Delegate CreatePropertyGetter(PropertyInfo propertyInfo, Type classType) { - MethodInfo realMethod = propertyInfo.GetGetMethod(); + MethodInfo? realMethod = propertyInfo.GetGetMethod(); Type objectType = typeof(object); + Debug.Assert(realMethod != null); var dynamicMethod = new DynamicMethod( realMethod.Name, propertyInfo.PropertyType, @@ -184,14 +177,15 @@ private static Delegate CreatePropertyGetter(PropertyInfo propertyInfo, Type cla return dynamicMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(objectType, propertyInfo.PropertyType)); } - public override Action CreatePropertySetter(PropertyInfo propertyInfo) => - (Action)CreatePropertySetter(propertyInfo, typeof(TClass)); + public override Action CreatePropertySetter(PropertyInfo propertyInfo) => + (Action)CreatePropertySetter(propertyInfo, typeof(TClass)); private static Delegate CreatePropertySetter(PropertyInfo propertyInfo, Type classType) { - MethodInfo realMethod = propertyInfo.GetSetMethod(); + MethodInfo? realMethod = propertyInfo.GetSetMethod(); Type objectType = typeof(object); + Debug.Assert(realMethod != null); var dynamicMethod = new DynamicMethod( realMethod.Name, typeof(void), diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionMemberAccessor.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionMemberAccessor.cs index 819dcc2d99094f..0560db9adfe5ce 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionMemberAccessor.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReflectionMemberAccessor.cs @@ -16,18 +16,18 @@ internal sealed class ReflectionMemberAccessor : MemberAccessor private delegate void SetProperty(TClass obj, TProperty value); private delegate void SetPropertyByRef(ref TClass obj, TProperty value); - private delegate Func GetPropertyByRefFactory(GetPropertyByRef set); - private delegate Action SetPropertyByRefFactory(SetPropertyByRef set); + private delegate Func GetPropertyByRefFactory(GetPropertyByRef set); + private delegate Action SetPropertyByRefFactory(SetPropertyByRef set); - private static readonly MethodInfo s_createStructPropertyGetterMethod = new GetPropertyByRefFactory(CreateStructPropertyGetter) + private static readonly MethodInfo s_createStructPropertyGetterMethod = new GetPropertyByRefFactory(CreateStructPropertyGetter!) .Method.GetGenericMethodDefinition(); - private static readonly MethodInfo s_createStructPropertySetterMethod = new SetPropertyByRefFactory(CreateStructPropertySetter) + private static readonly MethodInfo s_createStructPropertySetterMethod = new SetPropertyByRefFactory(CreateStructPropertySetter!) .Method.GetGenericMethodDefinition(); - public override JsonClassInfo.ConstructorDelegate CreateConstructor(Type type) + public override JsonClassInfo.ConstructorDelegate? CreateConstructor(Type type) { Debug.Assert(type != null); - ConstructorInfo realMethod = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, modifiers: null); + ConstructorInfo? realMethod = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, modifiers: null); if (type.IsAbstract) { @@ -53,18 +53,13 @@ public override ImmutableCollectionCreator ImmutableCollectionCreateRange(Type c { MethodInfo createRange = ImmutableCollectionCreateRangeMethod(constructingType, elementType); - if (createRange == null) - { - return null; - } - Type creatorType = typeof(ImmutableEnumerableCreator<,>).MakeGenericType(elementType, collectionType); ConstructorInfo constructor = creatorType.GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, - modifiers: null); + modifiers: null)!; ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor.Invoke(Array.Empty()); creator.RegisterCreatorDelegateFromMethod(createRange); @@ -84,27 +79,22 @@ public override ImmutableCollectionCreator ImmutableDictionaryCreateRange(Type c MethodInfo createRange = ImmutableDictionaryCreateRangeMethod(constructingType, elementType); - if (createRange == null) - { - return null; - } - Type creatorType = typeof(ImmutableDictionaryCreator<,>).MakeGenericType(elementType, collectionType); ConstructorInfo constructor = creatorType.GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, Type.EmptyTypes, - modifiers: null); + modifiers: null)!; ImmutableCollectionCreator creator = (ImmutableCollectionCreator)constructor.Invoke(Array.Empty()); creator.RegisterCreatorDelegateFromMethod(createRange); return creator; } - public override Func CreatePropertyGetter(PropertyInfo propertyInfo) + public override Func CreatePropertyGetter(PropertyInfo propertyInfo) { - MethodInfo getMethodInfo = propertyInfo.GetGetMethod(); + MethodInfo getMethodInfo = propertyInfo.GetGetMethod()!; if (typeof(TClass).IsValueType) { @@ -116,30 +106,30 @@ public override Func CreatePropertyGetter( else { var propertyGetter = CreateDelegate>(getMethodInfo); - return delegate (object obj) + return delegate (object? obj) { - return propertyGetter((TClass)obj); + return propertyGetter((TClass)obj!); }; } } - public override Action CreatePropertySetter(PropertyInfo propertyInfo) + public override Action CreatePropertySetter(PropertyInfo propertyInfo) { - MethodInfo setMethodInfo = propertyInfo.GetSetMethod(); + MethodInfo setMethodInfo = propertyInfo.GetSetMethod()!; if (typeof(TClass).IsValueType) { - var factory = CreateDelegate>(s_createStructPropertySetterMethod.MakeGenericMethod(typeof(TClass), typeof(TProperty))); - var propertySetter = CreateDelegate>(setMethodInfo); + SetPropertyByRefFactory factory = CreateDelegate>(s_createStructPropertySetterMethod.MakeGenericMethod(typeof(TClass), typeof(TProperty))); + SetPropertyByRef propertySetter = CreateDelegate>(setMethodInfo); return factory(propertySetter); } else { var propertySetter = CreateDelegate>(setMethodInfo); - return delegate (object obj, TProperty value) + return delegate (object? obj, TProperty value) { - propertySetter((TClass)obj, value); + propertySetter((TClass)obj!, value); }; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs index a9157b23aa0a1c..b35aa09baa555f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs @@ -39,7 +39,7 @@ public void Push() _index++; } - public void Push(JsonClassInfo nextClassInfo, object nextValue) + public void Push(JsonClassInfo nextClassInfo, object? nextValue) { Push(); Current.JsonClassInfo = nextClassInfo; @@ -84,11 +84,11 @@ public string PropertyPath() private void AppendStackFrame(StringBuilder sb, in WriteStackFrame frame) { // Append the property name. - string propertyName = frame.JsonPropertyInfo?.PropertyInfo?.Name; + string? propertyName = frame.JsonPropertyInfo?.PropertyInfo?.Name; AppendPropertyName(sb, propertyName); } - private void AppendPropertyName(StringBuilder sb, string propertyName) + private void AppendPropertyName(StringBuilder sb, string? propertyName) { if (propertyName != null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStackFrame.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStackFrame.cs index afa42b75a9fa7b..3a5adcea79dc17 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStackFrame.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStackFrame.cs @@ -12,14 +12,14 @@ namespace System.Text.Json internal struct WriteStackFrame { // The object (POCO or IEnumerable) that is being populated. - public object CurrentValue; - public JsonClassInfo JsonClassInfo; + public object? CurrentValue; + public JsonClassInfo? JsonClassInfo; // Support Dictionary keys. - public string KeyName; + public string? KeyName; // The current IEnumerable or IDictionary. - public IEnumerator CollectionEnumerator; + public IEnumerator? CollectionEnumerator; // Note all bools are kept together for packing: public bool PopStackOnEndCollection; @@ -31,7 +31,7 @@ internal struct WriteStackFrame // The current property. public int PropertyEnumeratorIndex; public ExtensionDataWriteStatus ExtensionDataStatus; - public JsonPropertyInfo JsonPropertyInfo; + public JsonPropertyInfo? JsonPropertyInfo; public void Initialize(Type type, JsonSerializerOptions options) { @@ -46,7 +46,7 @@ public void WriteObjectOrArrayStart(ClassType classType, Utf8JsonWriter writer, { if (JsonPropertyInfo?.EscapedName.HasValue == true) { - WriteObjectOrArrayStart(classType, JsonPropertyInfo.EscapedName.Value, writer, writeNull); + WriteObjectOrArrayStart(classType, JsonPropertyInfo.EscapedName!.Value, writer, writeNull); } else if (KeyName != null) { @@ -129,6 +129,7 @@ public void NextProperty() { EndProperty(); + Debug.Assert(JsonClassInfo != null && JsonClassInfo.PropertyCacheArray != null); int maxPropertyIndex = JsonClassInfo.PropertyCacheArray.Length; ++PropertyEnumeratorIndex; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 9cd7589737a4c0..4e9bca3fa3c9c5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; @@ -11,14 +12,16 @@ namespace System.Text.Json { internal static partial class ThrowHelper { + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentException_DeserializeWrongType(Type type, object value) { throw new ArgumentException(SR.Format(SR.DeserializeWrongType, type, value.GetType())); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static NotSupportedException GetNotSupportedException_SerializationNotSupportedCollection(Type propertyType, Type parentType, MemberInfo memberInfo) + public static NotSupportedException GetNotSupportedException_SerializationNotSupportedCollection(Type propertyType, Type? parentType, MemberInfo? memberInfo) { if (parentType != null && parentType != typeof(object) && memberInfo != null) { @@ -28,11 +31,13 @@ public static NotSupportedException GetNotSupportedException_SerializationNotSup return new NotSupportedException(SR.Format(SR.SerializationNotSupportedCollectionType, propertyType)); } + [DoesNotReturn] public static void ThrowInvalidOperationException_SerializerCycleDetected(int maxDepth) { throw new JsonException(SR.Format(SR.SerializerCycleDetected, maxDepth)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType) { @@ -41,49 +46,56 @@ public static void ThrowJsonException_DeserializeUnableToConvertValue(Type prope throw ex; } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType, string path, Exception innerException = null) + public static void ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType, string path, Exception? innerException = null) { string message = SR.Format(SR.DeserializeUnableToConvertValue, propertyType) + $" Path: {path}."; throw new JsonException(message, path, null, null, innerException); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowJsonException_DepthTooLarge(int currentDepth, JsonSerializerOptions options) { throw new JsonException(SR.Format(SR.DepthTooLarge, currentDepth, options.EffectiveMaxDepth)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowJsonException_SerializationConverterRead(JsonConverter converter) + public static void ThrowJsonException_SerializationConverterRead(JsonConverter? converter) { var ex = new JsonException(SR.Format(SR.SerializationConverterRead, converter)); ex.AppendPathInformation = true; throw ex; } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowJsonException_SerializationConverterWrite(JsonConverter converter) + public static void ThrowJsonException_SerializationConverterWrite(JsonConverter? converter) { var ex = new JsonException(SR.Format(SR.SerializationConverterWrite, converter)); ex.AppendPathInformation = true; throw ex; } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowJsonException() { throw new JsonException(); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializationConverterNotCompatible(Type converterType, Type type) { throw new InvalidOperationException(SR.Format(SR.SerializationConverterNotCompatible, converterType, type)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(Type classType, PropertyInfo propertyInfo) + public static void ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(Type classType, PropertyInfo? propertyInfo) { string location = classType.ToString(); if (propertyInfo != null) @@ -94,8 +106,9 @@ public static void ThrowInvalidOperationException_SerializationConverterOnAttrib throw new InvalidOperationException(SR.Format(SR.SerializationConverterOnAttributeInvalid, location)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(Type classTypeAttributeIsOn, PropertyInfo propertyInfo, Type typeToConvert) + public static void ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(Type classTypeAttributeIsOn, PropertyInfo? propertyInfo, Type typeToConvert) { string location = classTypeAttributeIsOn.ToString(); @@ -107,35 +120,38 @@ public static void ThrowInvalidOperationException_SerializationConverterOnAttrib throw new InvalidOperationException(SR.Format(SR.SerializationConverterOnAttributeNotCompatible, location, typeToConvert)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializerOptionsImmutable() { throw new InvalidOperationException(SR.SerializerOptionsImmutable); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializerPropertyNameConflict(JsonClassInfo jsonClassInfo, JsonPropertyInfo jsonPropertyInfo) { - throw new InvalidOperationException(SR.Format(SR.SerializerPropertyNameConflict, jsonClassInfo.Type, jsonPropertyInfo.PropertyInfo.Name)); + throw new InvalidOperationException(SR.Format(SR.SerializerPropertyNameConflict, jsonClassInfo.Type, jsonPropertyInfo.PropertyInfo?.Name)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializerPropertyNameNull(Type parentType, JsonPropertyInfo jsonPropertyInfo) { - throw new InvalidOperationException(SR.Format(SR.SerializerPropertyNameNull, parentType, jsonPropertyInfo.PropertyInfo.Name)); + throw new InvalidOperationException(SR.Format(SR.SerializerPropertyNameNull, parentType, jsonPropertyInfo.PropertyInfo?.Name)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializerDictionaryKeyNull(Type policyType) { throw new InvalidOperationException(SR.Format(SR.SerializerDictionaryKeyNull, policyType)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ReThrowWithPath(in ReadStack readStack, JsonReaderException ex) { - Debug.Assert(ex.Path == null); - string path = readStack.JsonPath(); string message = ex.Message; @@ -153,6 +169,7 @@ public static void ReThrowWithPath(in ReadStack readStack, JsonReaderException e throw new JsonException(message, path, ex.LineNumber, ex.BytePositionInLine, ex); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ReThrowWithPath(in ReadStack readStack, in Utf8JsonReader reader, Exception ex) { @@ -172,15 +189,15 @@ public static void AddExceptionInformation(in ReadStack readStack, in Utf8JsonRe string path = readStack.JsonPath(); ex.Path = path; - string message = ex.Message; + string? message = ex._message; if (string.IsNullOrEmpty(message)) { // Use a default message. - Type propertyType = readStack.Current.JsonPropertyInfo?.RuntimePropertyType; + Type? propertyType = readStack.Current.JsonPropertyInfo?.RuntimePropertyType; if (propertyType == null) { - propertyType = readStack.Current.JsonClassInfo.Type; + propertyType = readStack.Current.JsonClassInfo?.Type; } message = SR.Format(SR.DeserializeUnableToConvertValue, propertyType); @@ -194,6 +211,7 @@ public static void AddExceptionInformation(in ReadStack readStack, in Utf8JsonRe } } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ReThrowWithPath(in WriteStack writeStack, Exception ex) { @@ -207,7 +225,7 @@ public static void AddExceptionInformation(in WriteStack writeStack, JsonExcepti string path = writeStack.PropertyPath(); ex.Path = path; - string message = ex.Message; + string? message = ex._message; if (string.IsNullOrEmpty(message)) { // Use a default message. @@ -222,8 +240,9 @@ public static void AddExceptionInformation(in WriteStack writeStack, JsonExcepti } } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, Type classType, PropertyInfo propertyInfo) + public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, Type classType, PropertyInfo? propertyInfo) { string location = classType.ToString(); if (propertyInfo != null) @@ -234,18 +253,21 @@ public static void ThrowInvalidOperationException_SerializationDuplicateAttribut throw new InvalidOperationException(SR.Format(SR.SerializationDuplicateAttribute, attribute, location)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializationDuplicateTypeAttribute(Type classType, Type attribute) { throw new InvalidOperationException(SR.Format(SR.SerializationDuplicateTypeAttribute, classType, attribute)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowInvalidOperationException_SerializationDataExtensionPropertyInvalid(JsonClassInfo jsonClassInfo, JsonPropertyInfo jsonPropertyInfo) { - throw new InvalidOperationException(SR.Format(SR.SerializationDataExtensionPropertyInvalid, jsonClassInfo.Type, jsonPropertyInfo.PropertyInfo.Name)); + throw new InvalidOperationException(SR.Format(SR.SerializationDataExtensionPropertyInvalid, jsonClassInfo.Type, jsonPropertyInfo.PropertyInfo?.Name)); } + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(Type invalidType) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index cf4fd17a76253b..9dffc288b1a551 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace System.Text.Json @@ -34,6 +35,7 @@ private static ArgumentException GetArgumentException(string message) return new ArgumentException(message); } + [DoesNotReturn] public static void ThrowArgumentException(string message) { throw GetArgumentException(message); @@ -44,26 +46,31 @@ public static InvalidOperationException GetInvalidOperationException_CallFlushFi return GetInvalidOperationException(SR.Format(SR.CallFlushToAvoidDataLoss, _buffered)); } + [DoesNotReturn] public static void ThrowArgumentException_PropertyNameTooLarge(int tokenLength) { throw GetArgumentException(SR.Format(SR.PropertyNameTooLarge, tokenLength)); } + [DoesNotReturn] public static void ThrowArgumentException_ValueTooLarge(int tokenLength) { throw GetArgumentException(SR.Format(SR.ValueTooLarge, tokenLength)); } + [DoesNotReturn] public static void ThrowArgumentException_ValueNotSupported() { throw GetArgumentException(SR.SpecialNumberValuesNotSupported); } + [DoesNotReturn] public static void ThrowInvalidOperationException_NeedLargerSpan() { throw GetInvalidOperationException(SR.FailedToGetLargerSpan); } + [DoesNotReturn] public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) { if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize) @@ -77,6 +84,7 @@ public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadO } } + [DoesNotReturn] public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) { if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize) @@ -90,6 +98,7 @@ public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadO } } + [DoesNotReturn] public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) { if (propertyName.Length > JsonConstants.MaxCharacterTokenSize) @@ -103,6 +112,7 @@ public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadO } } + [DoesNotReturn] public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) { if (propertyName.Length > JsonConstants.MaxCharacterTokenSize) @@ -116,6 +126,7 @@ public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadO } } + [DoesNotReturn] public static void ThrowInvalidOperationOrArgumentException(ReadOnlySpan propertyName, int currentDepth) { currentDepth &= JsonConstants.RemoveFlagsBitMask; @@ -130,6 +141,7 @@ public static void ThrowInvalidOperationOrArgumentException(ReadOnlySpan p } } + [DoesNotReturn] public static void ThrowInvalidOperationException(int currentDepth) { currentDepth &= JsonConstants.RemoveFlagsBitMask; @@ -137,6 +149,7 @@ public static void ThrowInvalidOperationException(int currentDepth) ThrowInvalidOperationException(SR.Format(SR.DepthTooLarge, currentDepth, JsonConstants.MaxWriterDepth)); } + [DoesNotReturn] public static void ThrowInvalidOperationException(string message) { throw GetInvalidOperationException(message); @@ -150,6 +163,7 @@ private static InvalidOperationException GetInvalidOperationException(string mes return ex; } + [DoesNotReturn] public static void ThrowInvalidOperationException_DepthNonZeroOrEmptyJson(int currentDepth) { throw GetInvalidOperationException(currentDepth); @@ -169,6 +183,7 @@ private static InvalidOperationException GetInvalidOperationException(int curren } } + [DoesNotReturn] public static void ThrowInvalidOperationOrArgumentException(ReadOnlySpan propertyName, int currentDepth) { currentDepth &= JsonConstants.RemoveFlagsBitMask; @@ -260,6 +275,7 @@ internal static InvalidOperationException GetJsonElementWrongTypeException( SR.Format(SR.JsonElementHasWrongType, expectedTypeName, actualType)); } + [DoesNotReturn] public static void ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte = default, ReadOnlySpan bytes = default) { throw GetJsonReaderException(ref json, resource, nextByte, bytes); @@ -407,16 +423,19 @@ private static string GetResourceString(ref Utf8JsonReader json, ExceptionResour return message; } + [DoesNotReturn] public static void ThrowInvalidOperationException(ExceptionResource resource, int currentDepth, byte token, JsonTokenType tokenType) { throw GetInvalidOperationException(resource, currentDepth, token, tokenType); } + [DoesNotReturn] public static void ThrowArgumentException_InvalidCommentValue() { throw new ArgumentException(SR.CannotWriteCommentWithEmbeddedDelimiter); } + [DoesNotReturn] public static void ThrowArgumentException_InvalidUTF8(ReadOnlySpan value) { var builder = new StringBuilder(); @@ -444,16 +463,19 @@ public static void ThrowArgumentException_InvalidUTF8(ReadOnlySpan value) throw new ArgumentException(SR.Format(SR.CannotEncodeInvalidUTF8, builder)); } + [DoesNotReturn] public static void ThrowArgumentException_InvalidUTF16(int charAsInt) { throw new ArgumentException(SR.Format(SR.CannotEncodeInvalidUTF16, $"0x{charAsInt:X2}")); } + [DoesNotReturn] public static void ThrowInvalidOperationException_ReadInvalidUTF16(int charAsInt) { throw GetInvalidOperationException(SR.Format(SR.CannotReadInvalidUTF16, $"0x{charAsInt:X2}")); } + [DoesNotReturn] public static void ThrowInvalidOperationException_ReadInvalidUTF16() { throw GetInvalidOperationException(SR.CannotReadIncompleteUTF16); @@ -611,6 +633,11 @@ public static FormatException GetFormatException(DataType dateType) ex.Source = ExceptionSourceValueToRethrowAsJsonException; return ex; } + + public static InvalidOperationException GetInvalidOperationException_ExpectedChar(JsonTokenType tokenType) + { + return GetInvalidOperationException("char", tokenType); + } } internal enum ExceptionResource diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs index a6e0c8c9e79729..143375a9e7c044 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.Escaping.cs @@ -54,12 +54,12 @@ internal static partial class JsonWriterHelper private static bool NeedsEscapingNoBoundsCheck(char value) => AllowList[value] == 0; - public static int NeedsEscaping(ReadOnlySpan value, JavaScriptEncoder encoder) + public static int NeedsEscaping(ReadOnlySpan value, JavaScriptEncoder? encoder) { return (encoder ?? JavaScriptEncoder.Default).FindFirstCharacterToEncodeUtf8(value); } - public static unsafe int NeedsEscaping(ReadOnlySpan value, JavaScriptEncoder encoder) + public static unsafe int NeedsEscaping(ReadOnlySpan value, JavaScriptEncoder? encoder) { // Some implementations of JavaScriptEncoder.FindFirstCharacterToEncode may not accept // null pointers and guard against that. Hence, check up-front to return -1. @@ -100,7 +100,7 @@ private static void EscapeString(ReadOnlySpan value, Span destinatio written += encoderBytesWritten; } - public static void EscapeString(ReadOnlySpan value, Span destination, int indexOfFirstByteToEscape, JavaScriptEncoder encoder, out int written) + public static void EscapeString(ReadOnlySpan value, Span destination, int indexOfFirstByteToEscape, JavaScriptEncoder? encoder, out int written) { Debug.Assert(indexOfFirstByteToEscape >= 0 && indexOfFirstByteToEscape < value.Length); @@ -211,7 +211,7 @@ private static void EscapeString(ReadOnlySpan value, Span destinatio written += encoderCharsWritten; } - public static void EscapeString(ReadOnlySpan value, Span destination, int indexOfFirstByteToEscape, JavaScriptEncoder encoder, out int written) + public static void EscapeString(ReadOnlySpan value, Span destination, int indexOfFirstByteToEscape, JavaScriptEncoder? encoder, out int written) { Debug.Assert(indexOfFirstByteToEscape >= 0 && indexOfFirstByteToEscape < value.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs index 6805d97307b061..7691bb5e3a9883 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterOptions.cs @@ -19,7 +19,7 @@ public struct JsonWriterOptions /// /// The encoder to use when escaping strings, or to use the default encoder. /// - public JavaScriptEncoder Encoder { get; set; } + public JavaScriptEncoder? Encoder { get; set; } /// /// Defines whether the should pretty print the JSON which includes: diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs index 6952b37b7b7051..3c1802c9301e12 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs @@ -138,7 +138,7 @@ private void WriteBase64EscapeProperty(ReadOnlySpan propertyName, ReadOnly Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -161,7 +161,7 @@ private void WriteBase64EscapeProperty(ReadOnlySpan utf8PropertyName, Read Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs index f008bfcfa633ad..da5219b98771d5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTime.cs @@ -143,7 +143,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan propertyName, DateTime Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -166,7 +166,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan utf8PropertyName, Date Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs index f95fcfc03034f3..37cd479a2b7350 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.DateTimeOffset.cs @@ -142,7 +142,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan propertyName, DateTime Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -165,7 +165,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan utf8PropertyName, Date Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs index d15cf699d2557d..e4b05e79b30fd1 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Decimal.cs @@ -142,7 +142,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, decimal Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -165,7 +165,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, deci Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs index 280b7afb8537ce..f8ae05cc04c20e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Double.cs @@ -146,7 +146,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, double v Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -169,7 +169,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, doub Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs index 4dbf764b5f9f76..60ba0b03872d0d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Float.cs @@ -146,7 +146,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, float va Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -169,7 +169,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, floa Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.FormattedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.FormattedNumber.cs index 12647045fed021..b50c17c5e17c6d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.FormattedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.FormattedNumber.cs @@ -117,7 +117,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, ReadOnly Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -140,7 +140,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, Read Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs index 6828db502ab98f..b18a107c78b350 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Guid.cs @@ -142,7 +142,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan propertyName, Guid val Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -165,7 +165,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan utf8PropertyName, Guid Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs index d16539c304aad4..152f454c625024 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Literal.cs @@ -231,7 +231,7 @@ private void WriteLiteralEscapeProperty(ReadOnlySpan propertyName, ReadOnl Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -254,7 +254,7 @@ private void WriteLiteralEscapeProperty(ReadOnlySpan utf8PropertyName, Rea Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs index d74a1ec7c13e08..360bea1089d0c2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.SignedNumber.cs @@ -212,7 +212,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, long val Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -235,7 +235,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, long Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs index 2dee64cc6e59ce..6ca6f1569f4833 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs @@ -85,7 +85,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan propertyName, int firs { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; if (firstEscapeIndexProp != -1) { @@ -238,7 +238,7 @@ private void WriteStringEscapeProperty(ReadOnlySpan utf8PropertyName, int { Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; if (firstEscapeIndexProp != -1) { @@ -420,7 +420,7 @@ public void WriteString(string propertyName, JsonEncodedText value) /// as if were called. /// /// - public void WriteString(string propertyName, string value) + public void WriteString(string propertyName, string? value) { if (propertyName == null) { @@ -505,7 +505,7 @@ public void WriteString(ReadOnlySpan utf8PropertyName, ReadOnlySpan /// as if was called. /// /// - public void WriteString(JsonEncodedText propertyName, string value) + public void WriteString(JsonEncodedText propertyName, string? value) { if (value == null) { @@ -745,7 +745,7 @@ private void WriteStringHelperEscapeProperty(ReadOnlySpan propertyName, Re /// as if was called. /// /// - public void WriteString(ReadOnlySpan propertyName, string value) + public void WriteString(ReadOnlySpan propertyName, string? value) { if (value == null) { @@ -817,7 +817,7 @@ private void WriteStringHelperEscapeProperty(ReadOnlySpan utf8PropertyName /// as if was called. /// /// - public void WriteString(ReadOnlySpan utf8PropertyName, string value) + public void WriteString(ReadOnlySpan utf8PropertyName, string? value) { if (value == null) { @@ -834,7 +834,7 @@ private void WriteStringEscapeValueOnly(ReadOnlySpan escapedPropertyName, Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(firstEscapeIndex >= 0 && firstEscapeIndex < utf8Value.Length); - byte[] valueArray = null; + byte[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndex); @@ -857,7 +857,7 @@ private void WriteStringEscapeValueOnly(ReadOnlySpan escapedPropertyName, Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= value.Length); Debug.Assert(firstEscapeIndex >= 0 && firstEscapeIndex < value.Length); - char[] valueArray = null; + char[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndex); @@ -880,7 +880,7 @@ private void WriteStringEscapePropertyOnly(ReadOnlySpan propertyName, Read Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndex >= 0 && firstEscapeIndex < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndex); @@ -903,7 +903,7 @@ private void WriteStringEscapePropertyOnly(ReadOnlySpan utf8PropertyName, Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndex >= 0 && firstEscapeIndex < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndex); @@ -1002,8 +1002,8 @@ private void WriteStringEscapePropertyOrValue(ReadOnlySpan propertyName, R Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= value.Length); Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); - char[] valueArray = null; - char[] propertyArray = null; + char[]? valueArray = null; + char[]? propertyArray = null; if (firstEscapeIndexVal != -1) { @@ -1071,8 +1071,8 @@ private void WriteStringEscapePropertyOrValue(ReadOnlySpan utf8PropertyNam Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); - byte[] valueArray = null; - byte[] propertyArray = null; + byte[]? valueArray = null; + byte[]? propertyArray = null; if (firstEscapeIndexVal != -1) { @@ -1140,8 +1140,8 @@ private void WriteStringEscapePropertyOrValue(ReadOnlySpan propertyName, R Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); - byte[] valueArray = null; - char[] propertyArray = null; + byte[]? valueArray = null; + char[]? propertyArray = null; if (firstEscapeIndexVal != -1) { @@ -1209,8 +1209,8 @@ private void WriteStringEscapePropertyOrValue(ReadOnlySpan utf8PropertyNam Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= value.Length); Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); - char[] valueArray = null; - byte[] propertyArray = null; + char[]? valueArray = null; + byte[]? propertyArray = null; if (firstEscapeIndexVal != -1) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs index 1acd0fcfb409a5..48d95184454344 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.UnsignedNumber.cs @@ -221,7 +221,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan propertyName, ulong va Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); @@ -244,7 +244,7 @@ private void WriteNumberEscapeProperty(ReadOnlySpan utf8PropertyName, ulon Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs index 04f5793ae10c0f..41847b8582e92e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs @@ -39,7 +39,7 @@ private void ValidateWritingValue() [MethodImpl(MethodImplOptions.AggressiveInlining)] private void Base64EncodeAndWrite(ReadOnlySpan bytes, Span output, int encodingLength) { - byte[] outputText = null; + byte[]? outputText = null; Span encodedBytes = encodingLength <= JsonConstants.StackallocThreshold ? stackalloc byte[encodingLength] : diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs index b23463a7145270..ae07948e36d599 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.String.cs @@ -47,7 +47,7 @@ private void WriteStringValueHelper(ReadOnlySpan utf8Value) /// as if was called. /// /// - public void WriteStringValue(string value) + public void WriteStringValue(string? value) { if (value == null) { @@ -184,7 +184,7 @@ private void WriteStringEscapeValue(ReadOnlySpan value, int firstEscapeInd Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= value.Length); Debug.Assert(firstEscapeIndexVal >= 0 && firstEscapeIndexVal < value.Length); - char[] valueArray = null; + char[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); @@ -327,7 +327,7 @@ private void WriteStringEscapeValue(ReadOnlySpan utf8Value, int firstEscap Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8Value.Length); Debug.Assert(firstEscapeIndexVal >= 0 && firstEscapeIndexVal < utf8Value.Length); - byte[] valueArray = null; + byte[]? valueArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index 4a90fc55037505..9ba41e024b4b35 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -41,9 +41,9 @@ public sealed partial class Utf8JsonWriter : IDisposable, IAsyncDisposable private const int DefaultGrowthSize = 4096; private const int InitialGrowthSize = 256; - private IBufferWriter _output; - private Stream _stream; - private ArrayBufferWriter _arrayBufferWriter; + private IBufferWriter? _output; + private Stream? _stream; + private ArrayBufferWriter? _arrayBufferWriter; private Memory _memory; @@ -694,7 +694,7 @@ private void WriteStartEscapeProperty(ReadOnlySpan utf8PropertyName, byte Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < utf8PropertyName.Length); - byte[] propertyArray = null; + byte[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); @@ -837,7 +837,7 @@ private void WriteStartEscapeProperty(ReadOnlySpan propertyName, byte toke Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); Debug.Assert(firstEscapeIndexProp >= 0 && firstEscapeIndexProp < propertyName.Length); - char[] propertyArray = null; + char[]? propertyArray = null; int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); diff --git a/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.BadConverters.cs b/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.BadConverters.cs index 4be8dd20abbe9f..493e80a5eb520d 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.BadConverters.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/CustomConverterTests.BadConverters.cs @@ -332,5 +332,37 @@ public static void TypeHasMoreThanOneConverter() Assert.Contains("'System.Text.Json.Serialization.JsonConverterAttribute'", ex.Message); Assert.Contains("'System.Text.Json.Serialization.Tests.CustomConverterTests+PocoWithTwoConverters'", ex.Message); } + + [Fact] + public static void ConverterWithoutDefaultCtor() + { + string json = @"{""MyType"":""ABC""}"; + + InvalidOperationException ex = Assert.Throws(() => JsonSerializer.Deserialize(json)); + Assert.Contains("'System.Text.Json.Serialization.Tests.CustomConverterTests+ClassWithConverterWithoutPublicEmptyCtor'", ex.Message); + } + + [JsonConverter(typeof(ConverterWithoutPublicEmptyCtor))] + public class ClassWithConverterWithoutPublicEmptyCtor + { + public string MyType { get; set; } + } + + internal class ConverterWithoutPublicEmptyCtor : JsonConverter + { + public ConverterWithoutPublicEmptyCtor(int x) + { + } + + public override ClassWithConverterWithoutPublicEmptyCtor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, ClassWithConverterWithoutPublicEmptyCtor value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/Null.ReadTests.cs b/src/libraries/System.Text.Json/tests/Serialization/Null.ReadTests.cs index d0614cfdbace50..3068a3e6ac6417 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/Null.ReadTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/Null.ReadTests.cs @@ -3,7 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using Newtonsoft.Json; using Xunit; +using Xunit.Sdk; +using System.Threading.Tasks; +using System.IO; namespace System.Text.Json.Serialization.Tests { @@ -152,5 +156,40 @@ public static void NullAcceptsLeadingAndTrailingTrivia() Assert.Null(obj); } } + + [Fact] + public static void NullReadTestChar() + { + Assert.Throws(() => JsonSerializer.Deserialize("null")); + Assert.Throws(() => JsonSerializer.Deserialize("")); + Assert.Throws(() => JsonSerializer.Deserialize("1234")); + Assert.Throws(() => JsonSerializer.Deserialize("\"stringTooLong\"")); + Assert.Throws(() => JsonSerializer.Deserialize("\"\u0059\"B")); + Assert.Throws(() => JsonSerializer.Deserialize("\"\uD800\uDC00\"")); + Assert.Equal('a', JsonSerializer.Deserialize("\"a\"")); + Assert.Equal('Y', JsonSerializer.Deserialize("\"\u0059\"")); + } + + [ActiveIssue(1037)] + [Fact] + public static void ParseNullStringToStructShouldThrowJsonException() + { + string nullString = "null"; + Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(nullString)); + + JsonTestHelper.AssertThrows(reader, (reader) => JsonSerializer.Deserialize(ref reader)); + Assert.Throws(() => JsonSerializer.Deserialize(Encoding.UTF8.GetBytes(nullString))); + Assert.Throws(() => JsonSerializer.Deserialize(nullString)); + } + + [ActiveIssue(1037)] + [Fact] + public static async Task ParseNullStringShouldThrowJsonExceptionAsync() + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("null"))) + { + await Assert.ThrowsAsync(async () => await JsonSerializer.DeserializeAsync(stream)); + } + } } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs index c5feea340c20c6..a13f36661798b4 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/PropertyNameTests.cs @@ -430,6 +430,26 @@ public static void LongPropertyNames(int propertyLength, char ch) string jsonRoundTripped = JsonSerializer.Serialize(obj, options); Assert.Equal(json, jsonRoundTripped); } + + [Fact] + public static void BadNamingPolicy_ThrowsInvalidOperation() + { + var options = new JsonSerializerOptions { DictionaryKeyPolicy = new NullNamingPolicy() }; + + var inputPrimitive = new Dictionary + { + { "validKey", 1 } + }; + + Assert.Throws(() => JsonSerializer.Serialize(inputPrimitive, options)); + + var inputClass = new Dictionary + { + { "validKey", new OverridePropertyNameDesignTime_TestClass() } + }; + + Assert.Throws(() => JsonSerializer.Serialize(inputClass, options)); + } } public class OverridePropertyNameDesignTime_TestClass diff --git a/src/libraries/System.Text.Json/tests/Serialization/ReadValueTests.cs b/src/libraries/System.Text.Json/tests/Serialization/ReadValueTests.cs index 1e29cebd8aff4f..41e171532069c4 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ReadValueTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ReadValueTests.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Threading.Tasks; using Xunit; @@ -567,4 +569,19 @@ public static void TooLittleJsonForIntArray(string json) Assert.Equal(0, reader.BytesConsumed); } } + + public class FullNameNullTest + { + private static void EmptyGenericMethod(List param) + { + } + + [Fact] + public static void TypeFullNameNullTest() + { + MethodInfo[] methods = typeof(FullNameNullTest).GetMethods(BindingFlags.Static | BindingFlags.NonPublic); + ParameterInfo[] parameters = methods[0].GetParameters(); + Assert.Throws(() => JsonSerializer.Deserialize("{}", parameters[0].ParameterType)); + } + } } diff --git a/src/libraries/System.Text.Json/tests/Serialization/SpanTests.cs b/src/libraries/System.Text.Json/tests/Serialization/SpanTests.cs index 6640ea5e3e3d65..2d01d6e67506c0 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/SpanTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/SpanTests.cs @@ -84,8 +84,7 @@ public static void NullObjectOutput() byte[] encodedNull = Encoding.UTF8.GetBytes(@"null"); { - byte[] output = JsonSerializer.SerializeToUtf8Bytes(null, null); - Assert.Equal(encodedNull, output); + Assert.Throws(() => JsonSerializer.SerializeToUtf8Bytes(null, null)); } {