Skip to content

Commit

Permalink
Fix JsonElement.WriteTo handling of escaped property names (dotnet/co…
Browse files Browse the repository at this point in the history
…refx#40784)

This removes the duplicate switch statement from writing properties,
as the usage of the new WritePropertyName API on the writer simplifies the logic here.

Commit migrated from dotnet/corefx@2d2abb3
  • Loading branch information
bartonjs authored and ahsonkhan committed Sep 3, 2019
1 parent b6ecab3 commit 799ed5f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -855,45 +855,8 @@ private void WriteComplexElement(int index, Utf8JsonWriter writer)
writer.WriteEndArray();
continue;
case JsonTokenType.PropertyName:
{
DbRow propertyValue = _parsedData.Get(i + DbRow.Size);

ReadOnlySpan<byte> propertyName =
_utf8Json.Slice(row.Location, row.SizeOrLength).Span;

// "Move" to the value.
i += DbRow.Size;

switch (propertyValue.TokenType)
{
case JsonTokenType.String:
WriteString(propertyName, propertyValue, writer);
continue;
case JsonTokenType.Number:
writer.WriteNumber(
propertyName,
_utf8Json.Slice(propertyValue.Location, propertyValue.SizeOrLength).Span);
continue;
case JsonTokenType.True:
writer.WriteBoolean(propertyName, value: true);
continue;
case JsonTokenType.False:
writer.WriteBoolean(propertyName, value: false);
continue;
case JsonTokenType.Null:
writer.WriteNull(propertyName);
continue;
case JsonTokenType.StartObject:
writer.WriteStartObject(propertyName);
continue;
case JsonTokenType.StartArray:
writer.WriteStartArray(propertyName);
continue;
}

Debug.Fail($"Unexpected encounter with JsonTokenType {row.TokenType}");
break;
}
WritePropertyName(row, writer);
continue;
}

Debug.Fail($"Unexpected encounter with JsonTokenType {row.TokenType}");
Expand All @@ -902,7 +865,7 @@ private void WriteComplexElement(int index, Utf8JsonWriter writer)

private ReadOnlySpan<byte> UnescapeString(in DbRow row, out ArraySegment<byte> rented)
{
Debug.Assert(row.TokenType == JsonTokenType.String);
Debug.Assert(row.TokenType == JsonTokenType.String || row.TokenType == JsonTokenType.PropertyName);
int loc = row.Location;
int length = row.SizeOrLength;
ReadOnlySpan<byte> text = _utf8Json.Slice(loc, length).Span;
Expand Down Expand Up @@ -933,15 +896,13 @@ private static void ClearAndReturn(ArraySegment<byte> rented)
}
}

private void WriteString(ReadOnlySpan<byte> propertyName, in DbRow row, Utf8JsonWriter writer)
private void WritePropertyName(in DbRow row, Utf8JsonWriter writer)
{
ArraySegment<byte> rented = default;

try
{
writer.WriteString(
propertyName,
UnescapeString(row, out rented));
writer.WritePropertyName(UnescapeString(row, out rented));
}
finally
{
Expand Down
47 changes: 42 additions & 5 deletions src/libraries/System.Text.Json/tests/JsonElementWriteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,24 @@ public void WriteEverythingObject(bool indented)
"\"obj\":{\"arr\":[1,3,5,7,11]}}");
}

[Theory]
[InlineData(false)]
[InlineData(true)]
public void ReadWriteEscapedPropertyNames(bool indented)
{
const string jsonIn = " { \"p\\u0069zza\": 1, \"hello\\u003c\\u003e\": 2, \"normal\": 3 }";

WriteComplexValue(
indented,
jsonIn,
@"{
""pizza"": 1,
""hello\u003c\u003e"": 2,
""normal"": 3
}",
"{\"pizza\":1,\"hello\\u003c\\u003e\":2,\"normal\":3}");
}

[Theory]
[InlineData(false)]
[InlineData(true)]
Expand Down Expand Up @@ -1209,20 +1227,39 @@ private void WriteComplexValue(
string expectedMinimal)
{
var buffer = new ArrayBufferWriter<byte>(1024);
byte[] bufferOutput;

using (JsonDocument doc = PrepareDocument(jsonIn))
var options = new JsonWriterOptions
{
var options = new JsonWriterOptions
{
Indented = indented
};
Indented = indented
};

using (JsonDocument doc = PrepareDocument(jsonIn))
{
using (var writer = new Utf8JsonWriter(buffer, options))
{
WriteSingleValue(doc, writer);
}

JsonTestHelper.AssertContents(indented ? expectedIndent : expectedMinimal, buffer);

bufferOutput = buffer.WrittenSpan.ToArray();
}

// After reading the output and writing it again, it should be byte-for-byte identical.
{
string bufferString = Encoding.UTF8.GetString(bufferOutput);
buffer.Clear();

using (JsonDocument doc2 = PrepareDocument(bufferString))
{
using (var writer = new Utf8JsonWriter(buffer, options))
{
WriteSingleValue(doc2, writer);
}
}

Assert.True(buffer.WrittenSpan.SequenceEqual(bufferOutput));
}
}

Expand Down

0 comments on commit 799ed5f

Please sign in to comment.