diff --git a/docs/mdsource/serializer-settings.source.md b/docs/mdsource/serializer-settings.source.md index 1d2622261..dc3e4e51e 100644 --- a/docs/mdsource/serializer-settings.source.md +++ b/docs/mdsource/serializer-settings.source.md @@ -119,6 +119,29 @@ Result: snippet: Tests.AddIgnoreInstance.verified.txt +## Obsolete members ignored + +Members with an [ObsoleteAttribute](https://docs.microsoft.com/en-us/dotnet/api/system.obsoleteattribute) are ignored: + +snippet: WithObsoleteProp + +Result: + +snippet: Tests.WithObsoleteProp.verified.txt + + +## Including Obsolete members + +Obsolete members can be included using `IncludeObsoletes`: + +snippet: WithObsoletePropIncluded + +Result: + +snippet: Tests.WithObsoletePropIncluded.verified.txt + + + ## Ignore member by expressions To ignore members of a certain type using an expression: diff --git a/docs/serializer-settings.md b/docs/serializer-settings.md index 3109206a3..d5811cdec 100644 --- a/docs/serializer-settings.md +++ b/docs/serializer-settings.md @@ -28,6 +28,8 @@ Serialization settings can be customized at three levels: * [Scoped settings](#scoped-settings) * [Ignoring a type](#ignoring-a-type) * [Ignoring a instance](#ignoring-a-instance) + * [Obsolete members ignored](#obsolete-members-ignored) + * [Including Obsolete members](#including-obsolete-members) * [Ignore member by expressions](#ignore-member-by-expressions) * [Ignore member by name](#ignore-member-by-name) * [Members that throw](#members-that-throw) @@ -47,7 +49,7 @@ var settings = new JsonSerializerSettings DefaultValueHandling = DefaultValueHandling.Ignore }; ``` -snippet source | anchor +snippet source | anchor @@ -144,7 +146,7 @@ var target = new DateTimeTarget await Verify(target); ``` -snippet source | anchor +snippet source | anchor Results in the following: @@ -360,6 +362,85 @@ Result: +## Obsolete members ignored + +Members with an [ObsoleteAttribute](https://docs.microsoft.com/en-us/dotnet/api/system.obsoleteattribute) are ignored: + + + +```cs +class WithObsolete +{ + [Obsolete] + public string ObsoleteProperty { get; set; } + public string OtherProperty { get; set; } +} + +[Fact] +public Task WithObsoleteProp() +{ + var target = new WithObsolete + { + ObsoleteProperty = "value1", + OtherProperty = "value2" + }; + return Verify(target); +} +``` +snippet source | anchor + + +Result: + + + +```txt +{ + OtherProperty: 'value2' +} +``` +snippet source | anchor + + + +## Including Obsolete members + +Obsolete members can be included using `IncludeObsoletes`: + + + +```cs +[Fact] +public Task WithObsoletePropIncluded() +{ + var target = new WithObsolete + { + ObsoleteProperty = "value1", + OtherProperty = "value2" + }; + var settings = new VerifySettings(); + settings.ModifySerialization(_=> { _.IncludeObsoletes(); }); + return Verify(target, settings); +} +``` +snippet source | anchor + + +Result: + + + +```txt +{ + ObsoleteProperty: 'value1', + OtherProperty: 'value2' +} +``` +snippet source | anchor + + + + ## Ignore member by expressions To ignore members of a certain type using an expression: diff --git a/src/Verify.Tests/Tests.WithObsoleteProp.verified.txt b/src/Verify.Tests/Tests.WithObsoleteProp.verified.txt index 9e26dfeeb..2f492a852 100644 --- a/src/Verify.Tests/Tests.WithObsoleteProp.verified.txt +++ b/src/Verify.Tests/Tests.WithObsoleteProp.verified.txt @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + OtherProperty: 'value2' +} \ No newline at end of file diff --git a/src/Verify.Tests/Tests.WithObsoletePropIncluded.verified.txt b/src/Verify.Tests/Tests.WithObsoletePropIncluded.verified.txt new file mode 100644 index 000000000..80dc81e91 --- /dev/null +++ b/src/Verify.Tests/Tests.WithObsoletePropIncluded.verified.txt @@ -0,0 +1,4 @@ +{ + ObsoleteProperty: 'value1', + OtherProperty: 'value2' +} \ No newline at end of file diff --git a/src/Verify.Tests/Tests.cs b/src/Verify.Tests/Tests.cs index 918f324c6..ac89d61d6 100644 --- a/src/Verify.Tests/Tests.cs +++ b/src/Verify.Tests/Tests.cs @@ -378,26 +378,50 @@ class WithNotSupportedException { public Guid NotImplementedExceptionProperty => throw new NotSupportedException(); } + +#pragma warning disable 612 + + #region WithObsoleteProp + + class WithObsolete + { + [Obsolete] + public string ObsoleteProperty { get; set; } + public string OtherProperty { get; set; } + } [Fact] public Task WithObsoleteProp() { - var target = new WithObsolete(); + var target = new WithObsolete + { + ObsoleteProperty = "value1", + OtherProperty = "value2" + }; return Verify(target); } - class WithObsolete - { - Guid obsoleteProperty; + #endregion - [Obsolete] - public Guid ObsoleteProperty + #region WithObsoletePropIncluded + + [Fact] + public Task WithObsoletePropIncluded() + { + var target = new WithObsolete { - get { throw new NotImplementedException(); } - set => obsoleteProperty = value; - } + ObsoleteProperty = "value1", + OtherProperty = "value2" + }; + var settings = new VerifySettings(); + settings.ModifySerialization(_=> { _.IncludeObsoletes(); }); + return Verify(target, settings); } + #endregion + +#pragma warning restore 612 + [Fact] public Task Escaping() { diff --git a/src/Verify/Serialization/CustomContractResolver.cs b/src/Verify/Serialization/CustomContractResolver.cs index 42a5567dd..16f3eff3a 100644 --- a/src/Verify/Serialization/CustomContractResolver.cs +++ b/src/Verify/Serialization/CustomContractResolver.cs @@ -11,6 +11,7 @@ class CustomContractResolver : { bool ignoreEmptyCollections; bool ignoreFalse; + bool includeObsoletes; IReadOnlyDictionary> ignored; IReadOnlyList ignoredTypes; IReadOnlyList> ignoreMembersThatThrow; @@ -19,6 +20,7 @@ class CustomContractResolver : public CustomContractResolver( bool ignoreEmptyCollections, bool ignoreFalse, + bool includeObsoletes, IReadOnlyDictionary> ignored, IReadOnlyList ignoredTypes, IReadOnlyList> ignoreMembersThatThrow, @@ -29,6 +31,7 @@ class CustomContractResolver : Guard.AgainstNull(ignoreMembersThatThrow, nameof(ignoreMembersThatThrow)); this.ignoreEmptyCollections = ignoreEmptyCollections; this.ignoreFalse = ignoreFalse; + this.includeObsoletes = includeObsoletes; this.ignored = ignored; this.ignoredTypes = ignoredTypes; this.ignoreMembersThatThrow = ignoreMembersThatThrow; @@ -52,10 +55,13 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ property.ConfigureIfBool(member, ignoreFalse); - if (member.GetCustomAttribute(true) != null) + if (!includeObsoletes) { - property.Ignored = true; - return property; + if (member.GetCustomAttribute(true) != null) + { + property.Ignored = true; + return property; + } } if (ignoredTypes.Any(x => x.IsAssignableFrom(property.PropertyType))) diff --git a/src/Verify/Serialization/SerializationSettings.cs b/src/Verify/Serialization/SerializationSettings.cs index 0b232a532..fc7310824 100644 --- a/src/Verify/Serialization/SerializationSettings.cs +++ b/src/Verify/Serialization/SerializationSettings.cs @@ -35,7 +35,8 @@ public SerializationSettings Clone() ignoreMembersWithType = ignoreMembersWithType.Clone(), ignoredInstances = ignoredInstances.Clone(), scrubDateTimes = scrubDateTimes, - scrubGuids = scrubGuids + scrubGuids = scrubGuids, + includeObsoletes = includeObsoletes, }; } @@ -164,6 +165,7 @@ public JsonSerializerSettings BuildSettings() settings.ContractResolver = new CustomContractResolver( ignoreEmptyCollections, ignoreFalse, + includeObsoletes, ignoredMembers, ignoreMembersWithType, ignoreMembersThatThrow, @@ -224,5 +226,12 @@ internal void RegenSettings() { currentSettings = BuildSettings(); } + + bool includeObsoletes; + + public void IncludeObsoletes() + { + includeObsoletes = true; + } } } \ No newline at end of file diff --git a/src/Verify/Serialization/VerifySettings.cs b/src/Verify/Serialization/VerifySettings.cs index 77b91b882..24e1db32d 100644 --- a/src/Verify/Serialization/VerifySettings.cs +++ b/src/Verify/Serialization/VerifySettings.cs @@ -31,5 +31,6 @@ public void AddExtraSettings(Action action) serialization.AddExtraSettings(action); serialization.RegenSettings(); } + } } \ No newline at end of file