Skip to content
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

Added field support to JSON serializer #36986

Merged
merged 4 commits into from
Jul 14, 2020

Conversation

YohDeadfall
Copy link
Contributor

Fixes #876, continues #2192.

@layomia This is reworked version of what I did before. It has no tests (in progress), but I would like to get your comments as soon as possible. And yep, there were unanswered questions in the previous PR. Hope you will find some time to address them (:

@layomia
Copy link
Contributor

layomia commented May 26, 2020

Addressing questions from #2192:

Should we rename all parameters, fields and properties of type PropertyInfo to something having member as a part of the name?

I think the renaming done in the current PR is fine i.e. using MemberInfo rather thanPropertyInfo. To keep the size of the PR smaller, JsonPropertyInfo and co should not be renamed.

Having a text template to generate class/struct for visibility and fields would improve code coverage and remove duplication.

I'd be supportive of having a template to do this if you want to take this on in this PR, depending on the implementation. However, for the purpose of driving this feature in, I'd be satisfied with interspersing fields in the existing test objects.

Wrt. to coverage for the new code, we should have tests for all serializer features that apply to properties e.g. JsonExtensionData, JsonIgnore (including ignoring per-filed), JsonInclude, JsonConverterAttribute, JsonPropertyName, testing when ctor args map to fields, testing property name collisions etc. This is where the duplication may be more pronounced.

@layomia layomia added this to the 5.0 milestone May 26, 2020
Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. There are a couple new JsonSerializerOptions properties from #876 (comment) yet to be added. I brought up a few test cases to add. MemberAccessor review is pending on a fix for the CI failures.

@@ -148,6 +154,44 @@ public JsonClassInfo(Type type, JsonSerializerOptions options)
// Non-public properties should not be included for (de)serialization.
}
}

foreach (FieldInfo fieldInfo in currentType.GetFields(binding))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to extend the property visibility tests added in #32107 and #36936 to include collisions between field names, and collisions between property and field names.

@layomia
Copy link
Contributor

layomia commented Jun 2, 2020

Ping @YohDeadfall. Marking as ready-for review since we are close to the implementation we want. There's still some feedback above to be addressed.

@YohDeadfall
Copy link
Contributor Author

Already addressed some of them, but not pushed (running tests). Am trying to narrow how the changes cause CI failures.

@YohDeadfall
Copy link
Contributor Author

@layomia could you help me? After rebasing the PR and installing the latest .NET, am unable to build .NET anymore because of:

.nuget\packages\microsoft.dotnet.build.tasks.sharedframework.sdk\5.0.0-beta.20278.4\targets\framework.dependency.targets(445,5): error MSB3073: The command "\dotnet\runtime\artifacts\bin\coreclr\Windows_NT.x64.Debug\sharedFramework\crossgen.exe @\dotnet\runtime\artifacts\obj\netcoreapp\Debug\net5.0\win-x64\crossgen\System.Runtime.WindowsRuntime.rsp" exited with code -2146233031.

This blocks me from fixing the issue with constructors.

@YohDeadfall
Copy link
Contributor Author

Cleaning up artifacts helped.

@layomia
Copy link
Contributor

layomia commented Jun 17, 2020

@YohDeadfall anything blocking progress on this? I can look into the test failures if needed. Preview 7 snaps on Monday, and we are trying to get this in soon.

@YohDeadfall
Copy link
Contributor Author

Just time blocks it accidentally, nothing more. I aware of the failures and know how to fix them.

@layomia
Copy link
Contributor

layomia commented Jun 19, 2020

Looks like CI failures are due to the merge conflicts.

@layomia
Copy link
Contributor

layomia commented Jun 19, 2020

Are you holding off for green CI before adding tests?

@steveharter
Copy link
Member

Please add the two test classes from the prior PR @ #2192 and be sure to hook them up to TestData.ReadSuccessCases and TestData.WriteSuccessCases. Thanks

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is green 👍 We just need the tests now :)


string memberName = memberInfo.Name;

// The JsonPropertyNameAttribute or naming policy resulted in a collision.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've made a few changes recently to make sure we have the correct semantics for property name collisions. We should be sure to add tests to cover collisions between field names, and also between property and field names. Basically, we should extend this test suite:

[Fact]
public static void Serialize_NewSlotPublicProperty()
{
// Serialize
var obj = new ClassWithNewSlotProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{""MyString"":""NewDefaultValue""}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithNewSlotProperty>(json);
Assert.Equal("NewValue", ((ClassWithNewSlotProperty)obj).MyString);
Assert.Equal("DefaultValue", ((ClassWithInternalProperty)obj).MyString);
}
[Fact]
public static void Serialize_BasePublicProperty_ConflictWithDerivedPrivate()
{
// Serialize
var obj = new ClassWithNewSlotInternalProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{""MyString"":""DefaultValue""}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithNewSlotInternalProperty>(json);
Assert.Equal("NewValue", ((ClassWithPublicProperty)obj).MyString);
Assert.Equal("NewDefaultValue", ((ClassWithNewSlotInternalProperty)obj).MyString);
}
[Fact]
public static void Serialize_PublicProperty_ConflictWithPrivateDueAttributes()
{
// Serialize
var obj = new ClassWithPropertyNamingConflict();
// Newtonsoft.Json throws JsonSerializationException here because
// non-public properties are included when [JsonProperty] is placed on them.
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{""MyString"":""DefaultValue""}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
// Newtonsoft.Json throws JsonSerializationException here because
// non-public properties are included when [JsonProperty] is placed on them.
obj = JsonSerializer.Deserialize<ClassWithPropertyNamingConflict>(json);
Assert.Equal("NewValue", obj.MyString);
Assert.Equal("ConflictingValue", obj.ConflictingString);
}
[Fact]
public static void Serialize_PublicProperty_ConflictWithPrivateDuePolicy()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassWithPropertyPolicyConflict();
string json = JsonSerializer.Serialize(obj, options);
Assert.Equal(@"{""myString"":""DefaultValue""}", json);
// Deserialize
json = @"{""myString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithPropertyPolicyConflict>(json, options);
Assert.Equal("NewValue", obj.MyString);
Assert.Equal("ConflictingValue", obj.myString);
}
[Fact]
public static void Serialize_NewSlotPublicProperty_ConflictWithBasePublicProperty()
{
// Serialize
var obj = new ClassWithNewSlotDecimalProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{""MyNumeric"":1.5}", json);
// Deserialize
json = @"{""MyNumeric"":2.5}";
obj = JsonSerializer.Deserialize<ClassWithNewSlotDecimalProperty>(json);
Assert.Equal(2.5M, obj.MyNumeric);
}
[Fact]
public static void Serialize_NewSlotPublicProperty_SpecifiedJsonPropertyName()
{
// Serialize
var obj = new ClassWithNewSlotAttributedDecimalProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Contains(@"""MyNewNumeric"":1.5", json);
Assert.Contains(@"""MyNumeric"":1", json);
// Deserialize
json = @"{""MyNewNumeric"":2.5,""MyNumeric"":4}";
obj = JsonSerializer.Deserialize<ClassWithNewSlotAttributedDecimalProperty>(json);
Assert.Equal(4, ((ClassWithHiddenByNewSlotIntProperty)obj).MyNumeric);
Assert.Equal(2.5M, ((ClassWithNewSlotAttributedDecimalProperty)obj).MyNumeric);
}
[Fact]
public static void Ignore_NonPublicProperty()
{
// Serialize
var obj = new ClassWithInternalProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithInternalProperty>(json);
Assert.Equal("DefaultValue", obj.MyString);
}
[Fact]
public static void Ignore_NewSlotPublicPropertyIgnored()
{
// Serialize
var obj = new ClassWithIgnoredNewSlotProperty();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredNewSlotProperty>(json);
Assert.Equal("NewDefaultValue", ((ClassWithIgnoredNewSlotProperty)obj).MyString);
Assert.Equal("DefaultValue", ((ClassWithInternalProperty)obj).MyString);
}
[Fact]
public static void Ignore_BasePublicPropertyIgnored_ConflictWithDerivedPrivate()
{
// Serialize
var obj = new ClassWithIgnoredPublicPropertyAndNewSlotPrivate();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredPublicPropertyAndNewSlotPrivate>(json);
Assert.Equal("DefaultValue", ((ClassWithIgnoredPublicProperty)obj).MyString);
Assert.Equal("NewDefaultValue", ((ClassWithIgnoredPublicPropertyAndNewSlotPrivate)obj).MyString);
}
[Fact]
public static void Ignore_PublicProperty_ConflictWithPrivateDueAttributes()
{
// Serialize
var obj = new ClassWithIgnoredPropertyNamingConflictPrivate();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{}", json);
// Newtonsoft.Json has the following output because non-public properties are included when [JsonProperty] is placed on them.
// {"MyString":"ConflictingValue"}
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredPropertyNamingConflictPrivate>(json);
Assert.Equal("DefaultValue", obj.MyString);
Assert.Equal("ConflictingValue", obj.ConflictingString);
// The output for Newtonsoft.Json is:
// obj.ConflictingString = "NewValue"
// obj.MyString still equals "DefaultValue"
}
[Fact]
public static void Ignore_PublicProperty_ConflictWithPrivateDuePolicy()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassWithIgnoredPropertyPolicyConflictPrivate();
string json = JsonSerializer.Serialize(obj, options);
Assert.Equal(@"{}", json);
// Deserialize
json = @"{""myString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredPropertyPolicyConflictPrivate>(json, options);
Assert.Equal("DefaultValue", obj.MyString);
Assert.Equal("ConflictingValue", obj.myString);
}
[Fact]
public static void Ignore_PublicProperty_ConflictWithPublicDueAttributes()
{
// Serialize
var obj = new ClassWithIgnoredPropertyNamingConflictPublic();
string json = JsonSerializer.Serialize(obj);
Assert.Equal(@"{""MyString"":""ConflictingValue""}", json);
// Deserialize
json = @"{""MyString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredPropertyNamingConflictPublic>(json);
Assert.Equal("DefaultValue", obj.MyString);
Assert.Equal("NewValue", obj.ConflictingString);
}
[Fact]
public static void Ignore_PublicProperty_ConflictWithPublicDuePolicy()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassWithIgnoredPropertyPolicyConflictPublic();
string json = JsonSerializer.Serialize(obj, options);
Assert.Equal(@"{""myString"":""ConflictingValue""}", json);
// Deserialize
json = @"{""myString"":""NewValue""}";
obj = JsonSerializer.Deserialize<ClassWithIgnoredPropertyPolicyConflictPublic>(json, options);
Assert.Equal("DefaultValue", obj.MyString);
Assert.Equal("NewValue", obj.myString);
}
[Fact]
public static void Throw_PublicProperty_ConflictDueAttributes()
{
// Serialize
var obj = new ClassWithPropertyNamingConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj));
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassWithPropertyNamingConflictWhichThrows>(json));
}
[Fact]
public static void Throw_PublicProperty_ConflictDueAttributes_SingleInheritance()
{
// Serialize
var obj = new ClassInheritedWithPropertyNamingConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj));
// The output for Newtonsoft.Json is:
// {"MyString":"ConflictingValue"}
// Conflicts at different type-hierarchy levels that are not caused by
// deriving or the new keyword are allowed. Properties on more derived types win.
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassInheritedWithPropertyNamingConflictWhichThrows>(json));
// The output for Newtonsoft.Json is:
// obj.ConflictingString = "NewValue"
// obj.MyString still equals "DefaultValue"
}
[Fact]
public static void Throw_PublicProperty_ConflictDueAttributes_DoubleInheritance()
{
// Serialize
var obj = new ClassTwiceInheritedWithPropertyNamingConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj));
// The output for Newtonsoft.Json is:
// {"MyString":"ConflictingValue"}
// Conflicts at different type-hierarchy levels that are not caused by
// deriving or the new keyword are allowed. Properties on more derived types win.
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassTwiceInheritedWithPropertyNamingConflictWhichThrows>(json));
// The output for Newtonsoft.Json is:
// obj.ConflictingString = "NewValue"
// obj.MyString still equals "DefaultValue"
}
[Fact]
public static void Throw_PublicProperty_ConflictDuePolicy()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassWithPropertyPolicyConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj, options));
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassWithPropertyPolicyConflictWhichThrows>(json, options));
}
[Fact]
public static void Throw_PublicProperty_ConflictDuePolicy_SingleInheritance()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassInheritedWithPropertyPolicyConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj, options));
// The output for Newtonsoft.Json is:
// {"myString":"ConflictingValue"}
// Conflicts at different type-hierarchy levels that are not caused by
// deriving or the new keyword are allowed. Properties on more derived types win.
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassInheritedWithPropertyPolicyConflictWhichThrows>(json, options));
// The output for Newtonsoft.Json is:
// obj.myString = "NewValue"
// obj.MyString still equals "DefaultValue"
}
[Fact]
public static void Throw_PublicProperty_ConflictDuePolicy_DobuleInheritance()
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
// Serialize
var obj = new ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows();
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Serialize(obj, options));
// The output for Newtonsoft.Json is:
// {"myString":"ConflictingValue"}
// Conflicts at different type-hierarchy levels that are not caused by
// deriving or the new keyword are allowed. Properties on more derived types win.
// Deserialize
string json = @"{""MyString"":""NewValue""}";
Assert.Throws<InvalidOperationException>(
() => JsonSerializer.Deserialize<ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows>(json, options));
// The output for Newtonsoft.Json is:
// obj.myString = "NewValue"
// obj.MyString still equals "DefaultValue"
}
[Fact]
public static void HiddenPropertiesIgnored_WhenOverridesIgnored()
{
string serialized = JsonSerializer.Serialize(new DerivedClass_With_IgnoredOverride());
Assert.Equal(@"{}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_WithVisibleProperty_Of_DerivedClass_With_IgnoredOverride());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_IgnoredOverride_And_ConflictingPropertyName());
Assert.Equal(@"{""MyProp"":null}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_Ignored_NewProperty());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_WithConflictingNewMember());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_WithConflictingNewMember_Of_DifferentType());
Assert.Equal(@"{""MyProp"":0}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_Ignored_ConflictingNewMember());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_Ignored_ConflictingNewMember_Of_DifferentType());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_NewProperty_And_ConflictingPropertyName());
Assert.Equal(@"{""MyProp"":null}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_Ignored_NewProperty_Of_DifferentType());
Assert.Equal(@"{""MyProp"":false}", serialized);
serialized = JsonSerializer.Serialize(new DerivedClass_With_Ignored_NewProperty_Of_DifferentType_And_ConflictingPropertyName());
Assert.Equal(@"{""MyProp"":null}", serialized);
serialized = JsonSerializer.Serialize(new FurtherDerivedClass_With_ConflictingPropertyName());
Assert.Equal(@"{""MyProp"":null}", serialized);
// Here we differ from Newtonsoft.Json, where the output would be
// {"MyProp":null}
// Conflicts at different type-hierarchy levels that are not caused by
// deriving or the new keyword are allowed. Properties on more derived types win.
// This is invalid in System.Text.Json.
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(new DerivedClass_WithConflictingPropertyName()));
serialized = JsonSerializer.Serialize(new FurtherDerivedClass_With_IgnoredOverride());
Assert.Equal(@"{""MyProp"":null}", serialized);
}

@layomia
Copy link
Contributor

layomia commented Jul 6, 2020

@YohDeadfall, will you have some time soon to check on the failures here?

@YohDeadfall
Copy link
Contributor Author

Am on vacation till Saturday, so on Sunday will return back and finish the feature.

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM when these comments are addressed.

@@ -14,13 +14,13 @@ namespace System.Text.Json.Serialization
/// During deserializing, when using <see cref="object"/> a "null" JSON value is treated as a <c>null</c> object reference, and when using
/// <see cref="JsonElement"/> a "null" is treated as a JsonElement with <see cref="JsonElement.ValueKind"/> set to <see cref="JsonValueKind.Null"/>.
///
/// During serializing, the name of the extension data property is not included in the JSON;
/// During serializing, the name of the extension data member is not included in the JSON;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

member

change to property or field here and below.

public sealed class JsonIgnoreAttribute : JsonAttribute
{
/// <summary>
/// Specifies the condition that must be met before a property will be ignored.
/// Specifies the condition that must be met before a member will be ignored.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

property or field

@@ -30,9 +31,11 @@ public static void Read(Type classType, byte[] data)
public static void ReadFromStream(Type classType, byte[] data)
{
MemoryStream stream = new MemoryStream(data);
var options = new JsonSerializerOptions { IncludeFields = true };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need IncludeFields on line 48. This is the cause of the CI failures.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I pushed tests as is before going to vacation. Thought that would have some time, but had other interests there.

{
ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(propertyInfo, currentType);
ThrowHelper.ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(fieldInfo, currentType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test this code path by extending these tests:

[Theory]
[InlineData(typeof(ClassWithPrivateProperty_WithJsonIncludeProperty))]
[InlineData(typeof(ClassWithInternalProperty_WithJsonIncludeProperty))]
[InlineData(typeof(ClassWithProtectedProperty_WithJsonIncludeProperty))]
public static void NonPublicProperty_WithJsonInclude_Invalid(Type type)
{
InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize("", type));
string exAsStr = ex.ToString();
Assert.Contains("MyString", exAsStr);
Assert.Contains(type.ToString(), exAsStr);
Assert.Contains("JsonIncludeAttribute", exAsStr);
ex = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(Activator.CreateInstance(type), type));
exAsStr = ex.ToString();
Assert.Contains("MyString", exAsStr);
Assert.Contains(type.ToString(), exAsStr);
Assert.Contains("JsonIncludeAttribute", exAsStr);
}
private class ClassWithPrivateProperty_WithJsonIncludeProperty
{
[JsonInclude]
private string MyString { get; set; }
}
private class ClassWithInternalProperty_WithJsonIncludeProperty
{
[JsonInclude]
internal string MyString { get; }
}
private class ClassWithProtectedProperty_WithJsonIncludeProperty
{
[JsonInclude]
protected string MyString { get; private set; }
}
}

@@ -218,6 +218,8 @@ public sealed partial class JsonSerializerOptions
public System.Text.Encodings.Web.JavaScriptEncoder? Encoder { get { throw null; } set { } }
public bool IgnoreNullValues { get { throw null; } set { } }
public bool IgnoreReadOnlyProperties { get { throw null; } set { } }
public bool IgnoreReadOnlyFields { get { throw null; } set { } }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test using this option.

@@ -479,7 +481,7 @@ public abstract partial class JsonConverter
internal JsonConverter() { }
public abstract bool CanConvert(System.Type typeToConvert);
}
[System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Enum | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=false)]
[System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Enum | System.AttributeTargets.Property | System.AttributeTargets.Field, AllowMultiple=false)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test using the attribute on a field, along with JsonIgnoreAttribute, JsonIncludeAttribute, JsonExtensionDataAttribute & JsonPropertyName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some new tests, but not finished yet. For naming they already exist.

Copy link
Contributor

@layomia layomia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks for your contribution, @YohDeadfall.

@layomia
Copy link
Contributor

layomia commented Jul 14, 2020

Will address minor clean up.

@layomia layomia merged commit 8892364 into dotnet:master Jul 14, 2020
@YohDeadfall YohDeadfall deleted the json-field-support branch July 14, 2020 07:54
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 1, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 2, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 2, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 2, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 3, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 3, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ericmaino pushed a commit to ericmaino/elfie-arriba that referenced this pull request Sep 3, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
ViniciusSouza added a commit to ViniciusSouza/elfie-arriba that referenced this pull request Sep 4, 2020
By default the AspNet.Core Serializer on 3.0+ is the System.Text.Json, the current implementation of the library doesn't support Fields only Properties even public fields.

There is a change that will be part of .net 5.0 that will provide a option to change this behaviour
dotnet/runtime#36986
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JsonSerializer should support field as well as properties
4 participants