-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make GetPropertyCount public and fix its return value #106503
Changes from 5 commits
45818a8
0c6fc09
ea276ea
eebfb1a
77a6f19
2b0d0fb
baca560
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -681,6 +681,7 @@ public static void ParseSimpleObject() | |
string city = parsedObject.GetProperty("city").GetString(); | ||
int zip = parsedObject.GetProperty("zip").GetInt32(); | ||
|
||
Assert.Equal(7, parsedObject.GetPropertyCount()); | ||
Assert.True(parsedObject.TryGetProperty("age", out JsonElement age2)); | ||
Assert.Equal(30, age2.GetInt32()); | ||
|
||
|
@@ -704,6 +705,7 @@ public static void ParseNestedJson() | |
|
||
Assert.Equal(1, parsedObject.GetArrayLength()); | ||
JsonElement person = parsedObject[0]; | ||
Assert.Equal(5, person.GetPropertyCount()); | ||
double age = person.GetProperty("age").GetDouble(); | ||
string first = person.GetProperty("first").GetString(); | ||
string last = person.GetProperty("last").GetString(); | ||
|
@@ -902,6 +904,7 @@ public static void ReadNumber_1Byte(sbyte value) | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -999,6 +1002,7 @@ public static void ReadNumber_2Bytes(short value) | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1091,6 +1095,7 @@ public static void ReadSmallInteger(int value) | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1194,6 +1199,7 @@ public static void ReadMediumInteger(long value) | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1267,6 +1273,7 @@ public static void ReadLargeInteger(ulong value) | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1340,6 +1347,7 @@ public static void ReadTooLargeInteger() | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1379,6 +1387,7 @@ public static void ReadDateTimeAndDateTimeOffset(string jsonString, string expec | |
Assert.Throws<InvalidOperationException>(() => root.GetInt64()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetUInt64()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1462,6 +1471,7 @@ public static void ReadGuid(string jsonString, string expectedStr) | |
Assert.Throws<InvalidOperationException>(() => root.GetInt64()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetUInt64()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1564,6 +1574,7 @@ public static void ReadNonInteger(string str, double expectedDouble, float expec | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1654,6 +1665,7 @@ public static void ReadTooPreciseDouble() | |
Assert.Throws<InvalidOperationException>(() => root.GetDateTimeOffset()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetGuid()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetBoolean()); | ||
|
@@ -1735,6 +1747,7 @@ public static void CheckUseAfterDispose() | |
|
||
Assert.Throws<ObjectDisposedException>(() => root.ValueKind); | ||
Assert.Throws<ObjectDisposedException>(() => root.GetArrayLength()); | ||
Assert.Throws<ObjectDisposedException>(() => root.GetPropertyCount()); | ||
Assert.Throws<ObjectDisposedException>(() => root.EnumerateArray()); | ||
Assert.Throws<ObjectDisposedException>(() => root.EnumerateObject()); | ||
Assert.Throws<ObjectDisposedException>(() => root.GetDouble()); | ||
|
@@ -1793,6 +1806,7 @@ public static void CheckUseDefault() | |
Assert.Equal(JsonValueKind.Undefined, root.ValueKind); | ||
|
||
Assert.Throws<InvalidOperationException>(() => root.GetArrayLength()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetPropertyCount()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateArray()); | ||
Assert.Throws<InvalidOperationException>(() => root.EnumerateObject()); | ||
Assert.Throws<InvalidOperationException>(() => root.GetDouble()); | ||
|
@@ -2442,13 +2456,15 @@ public static void GetRawText() | |
|
||
using (JsonDocument doc = JsonDocument.Parse(json)) | ||
{ | ||
Assert.Equal(6, doc.RootElement.GetPropertyCount()); | ||
JsonElement.ObjectEnumerator enumerator = doc.RootElement.EnumerateObject(); | ||
Assert.True(enumerator.MoveNext(), "Move to first property"); | ||
JsonProperty property = enumerator.Current; | ||
|
||
Assert.Equal(" weird property name", property.Name); | ||
string rawText = property.ToString(); | ||
int crCount = rawText.Count(c => c == '\r'); | ||
Assert.Equal(2, property.Value.GetPropertyCount()); | ||
Assert.Equal(128 + crCount, rawText.Length); | ||
Assert.Equal('\"', rawText[0]); | ||
Assert.Equal(' ', rawText[1]); | ||
|
@@ -3437,6 +3453,39 @@ public static void ParseValue_AllowMultipleValues_TrailingContent() | |
JsonTestHelper.AssertThrows<JsonException>(ref reader, (ref Utf8JsonReader reader) => reader.Read()); | ||
} | ||
|
||
[Theory] | ||
[InlineData("""{ "foo" : [1], "test": false, "bar" : { "nested": 3 } }""", 3)] | ||
[InlineData("""{ "foo" : [1,2,3,4] }""", 1)] | ||
[InlineData("""{}""", 0)] | ||
[InlineData("""{ "foo" : {"nested:" : {"nested": 1, "bla": [1, 2, {"bla": 3}] } }, "test": true, "foo2" : {"nested:" : {"nested": 1, "bla": [1, 2, {"bla": 3}] } }}""", 3)] | ||
public static void TestGetPropertyCount(string json, int expectedCount) | ||
{ | ||
JsonElement element = JsonSerializer.Deserialize<JsonElement>(json); | ||
Assert.Equal(expectedCount, element.GetPropertyCount()); | ||
} | ||
|
||
eiriktsarpalis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[Fact] | ||
public static void VerifyGetPropertyCountUsingEnumerateObject() | ||
{ | ||
using (JsonDocument doc = JsonDocument.Parse(SR.ProjectLockJson)) | ||
{ | ||
CheckPropertyCountAgainstEnumerateObject(doc.RootElement); | ||
} | ||
|
||
void CheckPropertyCountAgainstEnumerateObject(JsonElement obj) | ||
{ | ||
Assert.Equal(obj.EnumerateObject().Count(), obj.GetPropertyCount()); | ||
|
||
foreach (JsonProperty prop in obj.EnumerateObject()) | ||
{ | ||
if (prop.Value.ValueKind == JsonValueKind.Object) | ||
{ | ||
CheckPropertyCountAgainstEnumerateObject(prop.Value); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should there also be something like
? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How did I miss that... I now also added checks for |
||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public static void EnsureResizeSucceeds() | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might make sense to validate if this comment is consistent with the current implementation, just to make sure we're not accidentally regressing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: For me it seemed that the comment was wrong because previously it wasn't always 1 for
StartObject
. Instead it was set to the same value as the third int (number of rows until the next value). See first and last line here:runtime/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs
Lines 990 to 994 in fc7a8e6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the comment was always wrong (at least, was wrong in the initial merge, maybe it was right when I wrote it during feature development).
Nothing noticed or cared that the value was wrong, because nothing read the value until DeepEquals was added... and I guess it didn't notice that it was wrong, because it was the "same wrong" when two things were equal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to decide if this means that we should backport the change to 9. Is it possible for the original values (number of rows) to be equal when the number of properties are not equal? Even if that wouldn't impact functional correctness, it would prompt the comparer to recurse into a more expensive property-wise comparison for differently-sized objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible to have equal number of rows when the number of properties are not equal:
Example 1
10 rows and 2 properties:
10 rows but 3 properties:
Example 2
7 rows and 1 property:
7 rows and 3 properties:
But I would say it is very unlikely that two unequal values accidentally have the same number of rows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I think we should try to backport this.