Skip to content

Commit 45fe624

Browse files
authored
Avoid string allocation and improve performance of JsonProperty.WriteTo (#90074)
* Avoid string allocation in WriteTo when possible. System.Text.Json.JsonProperty.WriteTo uses get_Name, calling JsonElement.GetPropertyName() which would allocate a string. Use ReadOnlySpan<byte> from the underlying UTF8 json, when possible, by adding helper methods into JsonDocument & JsonElement. Fix #88767 * Avoid alloc in unescaping & escaping. Current code unescapes & escapes property names and uses ToArray. Avoid alloc by adding internal GetRaw/WriteRaw methods. * Fix bugs on escaped property names Original code doesn't handle GetRaw/WriteRaw on escaped property names correctly. * Change IndexOf to Contains if possible. * Further avoid alloc by inlining GetUnescapedSpan Allocations are further avoided when the property name is shorter than JsonConstants.StackallocByteThreshold, by inlining JsonReaderHelper.GetUnescapedSpan. * Move writing logic to JsonElement; Shorten names of new methods; Add a test of writing out special names. * Move logic into JsonDocument * fix format * fix format 2 * improve comment * removed unused stub * added assertion * removed unnecessary test
1 parent d563d0e commit 45fe624

3 files changed

Lines changed: 25 additions & 1 deletion

File tree

src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,15 @@ private static void ClearAndReturn(ArraySegment<byte> rented)
874874
}
875875
}
876876

877+
internal void WritePropertyName(int index, Utf8JsonWriter writer)
878+
{
879+
CheckNotDisposed();
880+
881+
DbRow row = _parsedData.Get(index - DbRow.Size);
882+
Debug.Assert(row.TokenType == JsonTokenType.PropertyName);
883+
WritePropertyName(row, writer);
884+
}
885+
877886
private void WritePropertyName(in DbRow row, Utf8JsonWriter writer)
878887
{
879888
ArraySegment<byte> rented = default;

src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonElement.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,13 @@ public void WriteTo(Utf8JsonWriter writer)
13161316
_parent.WriteElementTo(_idx, writer);
13171317
}
13181318

1319+
internal void WritePropertyNameTo(Utf8JsonWriter writer)
1320+
{
1321+
CheckValidInstance();
1322+
1323+
_parent.WritePropertyName(_idx, writer);
1324+
}
1325+
13191326
/// <summary>
13201327
/// Get an enumerator to enumerate the values in the JSON array represented by this JsonElement.
13211328
/// </summary>

src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonProperty.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,15 @@ public void WriteTo(Utf8JsonWriter writer)
117117
ThrowHelper.ThrowArgumentNullException(nameof(writer));
118118
}
119119

120-
writer.WritePropertyName(Name);
120+
if (_name is null)
121+
{
122+
Value.WritePropertyNameTo(writer);
123+
}
124+
else
125+
{
126+
writer.WritePropertyName(_name);
127+
}
128+
121129
Value.WriteTo(writer);
122130
}
123131

0 commit comments

Comments
 (0)