diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs index 5b9dbda76e5f13..5341f9d295d1a1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs @@ -40,6 +40,9 @@ public StringSyntaxAttribute(string syntax, params object?[] arguments) /// The syntax identifier for strings containing date and time format specifiers. public const string DateTimeFormat = nameof(DateTimeFormat); + /// The syntax identifier for strings containing JavaScript Object Notation (JSON). + public const string Json = nameof(Json); + /// The syntax identifier for strings containing regular expressions. public const string Regex = nameof(Regex); } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 851f9dcc38714c..3842060c647030 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9187,6 +9187,7 @@ public StringSyntaxAttribute(string syntax, params object?[] arguments) { } public string Syntax { get { throw null; } } public object?[] Arguments { get { throw null; } } public const string DateTimeFormat = "DateTimeFormat"; + public const string Json = "Json"; public const string Regex = "Regex"; } [System.AttributeUsageAttribute(System.AttributeTargets.All, Inherited=false, AllowMultiple=true)] diff --git a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs index 2dde50c727a3f0..ba53ab2c0f3bbe 100644 --- a/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs +++ b/src/libraries/System.Runtime/tests/System/Diagnostics/CodeAnalysis/StringSyntaxAttributeTests.cs @@ -9,6 +9,7 @@ public sealed class StringSyntaxAttributeTests { [Theory] [InlineData(StringSyntaxAttribute.DateTimeFormat)] + [InlineData(StringSyntaxAttribute.Json)] [InlineData(StringSyntaxAttribute.Regex)] public void Ctor_Roundtrips(string syntax) { 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 f6b25cdcb23d41..2bae8025f0ca02 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -20,8 +20,8 @@ public void Dispose() { } public static System.Text.Json.JsonDocument Parse(System.Buffers.ReadOnlySequence utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.JsonDocument Parse(System.IO.Stream utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.JsonDocument Parse(System.ReadOnlyMemory utf8Json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.JsonDocument Parse(System.ReadOnlyMemory json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.JsonDocument Parse(string json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlyMemory json, System.Text.Json.JsonDocumentOptions options = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.JsonDocument Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] 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, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.JsonDocument? document) { throw null; } @@ -193,11 +193,11 @@ 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(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static object? Deserialize(System.ReadOnlySpan json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static object? Deserialize(System.ReadOnlySpan json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static object? Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static object? Deserialize(string json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] public static object? Deserialize(this System.Text.Json.JsonDocument document, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static object? Deserialize(this System.Text.Json.JsonDocument document, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) { throw null; } @@ -225,11 +225,11 @@ public static partial class JsonSerializer public static TValue? Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static TValue? Deserialize(System.ReadOnlySpan utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static TValue? Deserialize(System.ReadOnlySpan json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static TValue? Deserialize(System.ReadOnlySpan json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] - public static TValue? Deserialize(string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } - public static TValue? Deserialize(string json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static TValue? Deserialize([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] public static TValue? Deserialize(this System.Text.Json.JsonDocument document, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static TValue? Deserialize(this System.Text.Json.JsonDocument document, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) { throw null; } @@ -511,9 +511,9 @@ public void WritePropertyName(System.ReadOnlySpan utf8PropertyName) { } public void WritePropertyName(System.ReadOnlySpan propertyName) { } public void WritePropertyName(string propertyName) { } public void WritePropertyName(System.Text.Json.JsonEncodedText propertyName) { } - public void WriteRawValue(string json, bool skipInputValidation = false) { } + public void WriteRawValue([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, bool skipInputValidation = false) { } public void WriteRawValue(System.ReadOnlySpan utf8Json, bool skipInputValidation = false) { } - public void WriteRawValue(System.ReadOnlySpan json, bool skipInputValidation = false) { } + public void WriteRawValue([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] System.ReadOnlySpan json, bool skipInputValidation = false) { } public void WriteStartArray() { } public void WriteStartArray(System.ReadOnlySpan utf8PropertyName) { } public void WriteStartArray(System.ReadOnlySpan propertyName) { } @@ -682,7 +682,7 @@ internal JsonNode() { } public static implicit operator System.Text.Json.Nodes.JsonNode (ulong value) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(System.IO.Stream utf8Json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(System.ReadOnlySpan utf8Json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } - public static System.Text.Json.Nodes.JsonNode? Parse(string json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } + public static System.Text.Json.Nodes.JsonNode? Parse([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.Json)] string json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; } public static System.Text.Json.Nodes.JsonNode? Parse(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?)) { throw null; } public string ToJsonString(System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public override string ToString() { 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 13c5c50fbc0e55..a468f99d4e1bce 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj @@ -20,6 +20,10 @@ + + + + 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 3c9c90848ff364..d24617f74a3d31 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -322,6 +322,9 @@ System.Text.Json.Nodes.JsonValue + + + 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 0e7446601716c1..6ceaa0af7dd950 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 @@ -247,7 +247,7 @@ private static async Task ParseAsyncCore( /// /// contains unsupported options. /// - public static JsonDocument Parse(ReadOnlyMemory json, JsonDocumentOptions options = default) + public static JsonDocument Parse([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlyMemory json, JsonDocumentOptions options = default) { ReadOnlySpan jsonChars = json.Span; int expectedByteCount = JsonReaderHelper.GetUtf8ByteCount(jsonChars); @@ -311,7 +311,7 @@ internal static JsonDocument ParseValue(ReadOnlyMemory json, JsonDocumentO /// /// contains unsupported options. /// - public static JsonDocument Parse(string json, JsonDocumentOptions options = default) + public static JsonDocument Parse([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonDocumentOptions options = default) { if (json == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs index e59eedb567b060..0d6f3a75263ebf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Parse.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.Json.Serialization.Converters; @@ -65,7 +66,7 @@ public abstract partial class JsonNode /// does not represent a valid single JSON value. /// public static JsonNode? Parse( - string json, + [StringSyntax(StringSyntaxAttribute.Json)] string json, JsonNodeOptions? nodeOptions = null, JsonDocumentOptions documentOptions = default(JsonDocumentOptions)) { 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 8606c9b1efc496..9056413479aca0 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 @@ -42,7 +42,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static TValue? Deserialize(string json, JsonSerializerOptions? options = null) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonSerializerOptions? options = null) { if (json == null) { @@ -78,7 +78,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static TValue? Deserialize(ReadOnlySpan json, JsonSerializerOptions? options = null) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, JsonSerializerOptions? options = null) { // default/null span is treated as empty @@ -114,7 +114,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static object? Deserialize(string json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, Type returnType, JsonSerializerOptions? options = null) { if (json == null) { @@ -158,7 +158,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [RequiresUnreferencedCode(SerializationUnreferencedCodeMessage)] - public static object? Deserialize(ReadOnlySpan json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, Type returnType, JsonSerializerOptions? options = null) { // default/null span is treated as empty @@ -202,7 +202,7 @@ 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, JsonTypeInfo jsonTypeInfo) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, JsonTypeInfo jsonTypeInfo) { // default/null span is treated as empty @@ -250,7 +250,7 @@ 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(ReadOnlySpan json, JsonTypeInfo jsonTypeInfo) + public static TValue? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, JsonTypeInfo jsonTypeInfo) { // default/null span is treated as empty @@ -297,7 +297,7 @@ 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 object? Deserialize(string json, Type returnType, JsonSerializerContext context) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] string json, Type returnType, JsonSerializerContext context) { if (json == null) { @@ -353,7 +353,7 @@ 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 object? Deserialize(ReadOnlySpan json, Type returnType, JsonSerializerContext context) + public static object? Deserialize([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, Type returnType, JsonSerializerContext context) { if (returnType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs index 5ac9c8cebe315e..d1a5c504993f8a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Text.Json { @@ -30,7 +31,7 @@ public sealed partial class Utf8JsonWriter /// /// The and values for the writer instance are not applied when using this method. /// - public void WriteRawValue(string json, bool skipInputValidation = false) + public void WriteRawValue([StringSyntax(StringSyntaxAttribute.Json)] string json, bool skipInputValidation = false) { if (!_options.SkipValidation) { @@ -66,7 +67,7 @@ public void WriteRawValue(string json, bool skipInputValidation = false) /// /// The and values for the writer instance are not applied when using this method. /// - public void WriteRawValue(ReadOnlySpan json, bool skipInputValidation = false) + public void WriteRawValue([StringSyntax(StringSyntaxAttribute.Json)] ReadOnlySpan json, bool skipInputValidation = false) { if (!_options.SkipValidation) {