Skip to content

Commit 195de03

Browse files
authored
Add ToString() to SqlJson (#3427)
1 parent 27ab95a commit 195de03

File tree

9 files changed

+252
-220
lines changed

9 files changed

+252
-220
lines changed

.editorconfig

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,12 @@ csharp_space_between_method_declaration_parameter_list_parentheses = false
132132
csharp_space_between_parentheses = false
133133
csharp_space_between_square_brackets = false
134134

135-
# Xml project files
135+
# Analyzers
136+
137+
dotnet_code_quality.ca1802.api_surface = private, internal
138+
139+
# CA2000: Dispose objects before losing scope
140+
dotnet_diagnostic.CA2000.severity = suggestion
136141

137142
# CA1063: Implement IDisposable Correctly
138143
dotnet_diagnostic.CA1063.severity = silent
@@ -143,6 +148,10 @@ dotnet_diagnostic.CA2100.severity = silent
143148
# CA1416: Validate platform compatibility
144149
dotnet_diagnostic.CA1416.severity = silent
145150

151+
dotnet_code_quality.CA2100.excluded_type_names_with_derived_types = Microsoft.Data.SqlClient.ManualTesting.Tests.*
152+
dotnet_diagnostic.xUnit1031.severity=none
153+
dotnet_diagnostic.xUnit1030.severity=none
154+
146155
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
147156
indent_size = 2
148157

@@ -163,13 +172,3 @@ indent_size = 2
163172
end_of_line = lf
164173
[*.{cmd, bat}]
165174
end_of_line = crlf
166-
167-
# Analyzers
168-
dotnet_code_quality.ca1802.api_surface = private, internal
169-
170-
[*.cs]
171-
dotnet_code_quality.CA2100.excluded_type_names_with_derived_types = Microsoft.Data.SqlClient.ManualTesting.Tests.*
172-
dotnet_diagnostic.xUnit1031.severity=none
173-
dotnet_diagnostic.xUnit1030.severity=none
174-
175-
Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,69 @@
1-
<?xml version="1.0"?>
1+
<?xml version="1.0" encoding="UTF-8" ?>
22
<docs>
33
<members name="SqlJson">
44
<SqlJson>
55
<summary>Represents the JSON datatype in SQL Server.</summary>
66
</SqlJson>
77
<ctor1>
8-
<summary>Parameterless constructor. Initializes a new instance of the SqlJson class which represents a null JSON value.</summary>
8+
<summary>
9+
Construct a new instance of the SqlJson class which represents a null
10+
JSON value.
11+
</summary>
912
</ctor1>
1013
<ctor2>
11-
<param name="jsonString"></param>
12-
<summary>Takes a <see cref="string"/> as input and initializes a new instance of the SqlJson class.</summary>
14+
<summary>
15+
Construct a new instance of the SqlJson class with a serialized JSON
16+
<see cref="string"/>. The string is validated by parsing it with
17+
<see cref="System.Text.Json.JsonDocument"/>.
18+
</summary>
19+
<param name="jsonString">
20+
The serialized JSON string to use, or null.
21+
</param>
22+
<throw>
23+
<exception cref="System.Text.Json.JsonException">
24+
If the given string is not valid JSON.
25+
</exception>
26+
</throw>
1327
</ctor2>
1428
<ctor3>
15-
<param name="jsonDoc"></param>
16-
<summary>Takes a <see cref="System.Text.Json.JsonDocument"/> as input and initializes a new instance of the SqlJson class.</summary>
29+
<summary>
30+
Construct a new instance of the SqlJson class with a
31+
<see cref="System.Text.Json.JsonDocument"/>. The serialized JSON string
32+
from the document is saved.
33+
</summary>
34+
<param name="jsonDoc">
35+
The document to use, or null.
36+
</param>
37+
<throw>
38+
<exception cref="System.ObjectDisposedException">
39+
If the given document has been disposed of.
40+
</exception>
41+
</throw>
1742
</ctor3>
1843
<IsNull>
1944
<inheritdoc/>
2045
</IsNull>
2146
<Null>
22-
<summary>Represents a null instance of the <see cref="SqlJson"/> type.</summary>
47+
<summary>
48+
Represents a null instance of the <see cref="SqlJson"/> type. This
49+
instance is equivalent to calling the parameterless constructor, or
50+
calling the other constructors with a null value.
51+
</summary>
2352
</Null>
2453
<Value>
25-
<summary>Gets the string representation of the Json content of this <see cref="SqlJson" /> instance.</summary>
54+
<summary>
55+
Gets the serialized JSON string of this <see cref="SqlJson" /> instance.
56+
</summary>
57+
<throw>
58+
<exception cref="System.Data.SqlTypes.SqlNullValueException">
59+
If the JSON value is null.
60+
</exception>
61+
</throw>
2662
</Value>
63+
<ToString>
64+
<summary>
65+
Returns the serialized JSON string, or null.
66+
</summary>
67+
</ToString>
2768
</members>
2869
</docs>

src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ public SqlJson(System.Text.Json.JsonDocument jsonDoc) { }
116116
public static SqlJson Null => throw null;
117117
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/Value/*' />
118118
public string Value { get { throw null; } }
119+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ToString/*' />
120+
public override string ToString() { throw null; }
119121
}
120122
}
121123
namespace Microsoft.Data.SqlClient

src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,5 +2408,7 @@ public SqlJson(System.Text.Json.JsonDocument jsonDoc) { }
24082408
public static SqlJson Null => throw null;
24092409
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/Value/*' />
24102410
public string Value { get { throw null; } }
2411+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ToString/*' />
2412+
public override string ToString() { throw null; }
24112413
}
24122414
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlJson.cs

Lines changed: 31 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,63 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
65
using System.Data.SqlTypes;
7-
using System.Text;
6+
#if NET
7+
using System.Diagnostics.CodeAnalysis;
8+
#endif
89
using System.Text.Json;
910

1011
#nullable enable
1112

1213
namespace Microsoft.Data.SqlTypes
1314
{
14-
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/SqlJson/*' />
15+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/SqlJson/*' />
1516
public class SqlJson : INullable
1617
{
17-
18-
/// <summary>
19-
/// True if null.
20-
/// </summary>
21-
private bool _isNull;
22-
23-
private readonly string? _jsonString;
18+
// Our serialized JSON string, or null.
19+
private readonly string? _jsonString = null;
2420

2521
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ctor1/*' />
2622
public SqlJson()
2723
{
28-
SetNull();
2924
}
3025

3126
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ctor2/*' />
32-
public SqlJson(string? jsonString)
27+
#if NET
28+
public SqlJson([StringSyntax(StringSyntaxAttribute.Json)] string? jsonString)
29+
#else
30+
public SqlJson(string? jsonString)
31+
#endif
3332
{
3433
if (jsonString == null)
3534
{
36-
SetNull();
37-
}
38-
else
39-
{
40-
// TODO: We need to validate the Json before storing it.
41-
ValidateJson(jsonString);
42-
_jsonString = jsonString;
35+
return;
4336
}
37+
38+
// Ask JsonDocument to parse it for validity, or throw.
39+
//
40+
// Note that we do not support trailing commas or comments in the
41+
// JSON.
42+
//
43+
JsonDocument.Parse(jsonString).Dispose();
44+
45+
_jsonString = jsonString;
4446
}
4547

4648
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ctor3/*' />
4749
public SqlJson(JsonDocument? jsonDoc)
4850
{
4951
if (jsonDoc == null)
5052
{
51-
SetNull();
52-
}
53-
else
54-
{
55-
_jsonString = jsonDoc.RootElement.GetRawText();
53+
return;
5654
}
55+
56+
// Save the serialized JSON string from the document, or throw.
57+
_jsonString = jsonDoc.RootElement.GetRawText();
5758
}
5859

5960
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/IsNull/*' />
60-
public bool IsNull => _isNull;
61+
public bool IsNull => _jsonString is null;
6162

6263
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/Null/*' />
6364
public static SqlJson Null => new();
@@ -71,33 +72,15 @@ public string Value
7172
{
7273
throw new SqlNullValueException();
7374
}
74-
else
75-
{
76-
return _jsonString!;
77-
}
78-
}
79-
}
8075

81-
private void SetNull()
82-
{
83-
_isNull = true;
76+
return _jsonString!;
77+
}
8478
}
8579

86-
private static void ValidateJson(string jsonString)
80+
/// <include file='../../../../doc/snippets/Microsoft.Data.SqlTypes/SqlJson.xml' path='docs/members[@name="SqlJson"]/ToString/*' />
81+
public override string? ToString()
8782
{
88-
// Convert the JSON string to a UTF-8 byte array
89-
byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
90-
91-
// Create a Utf8JsonReader instance
92-
var reader = new Utf8JsonReader(jsonBytes, isFinalBlock: true, state: default);
93-
94-
// Read through the JSON data
95-
while (reader.Read())
96-
{
97-
// The Read method advances the reader to the next token
98-
// If the JSON is invalid, an exception will be thrown
99-
}
100-
// If we reach here, the JSON is valid
83+
return _jsonString;
10184
}
10285
}
10386
}

0 commit comments

Comments
 (0)