Skip to content

Commit

Permalink
Add JsonIgnoreCondition.WhenWritingNull (#39388)
Browse files Browse the repository at this point in the history
* Add JsonIgnoreCondition.WhenWritingNull

* Address review feedback
  • Loading branch information
layomia authored Jul 16, 2020
1 parent 950ef6f commit 9b3cbc4
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/libraries/System.Text.Json/ref/System.Text.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ public enum JsonIgnoreCondition
Never = 0,
Always = 1,
WhenWritingDefault = 2,
WhenWritingNull = 3,
}
public abstract partial class JsonAttribute : System.Attribute
{
Expand Down
5 changes: 4 additions & 1 deletion src/libraries/System.Text.Json/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -533,4 +533,7 @@
<data name="DictionaryKeyTypeNotSupported" xml:space="preserve">
<value>The type '{0}' is not a supported Dictionary key type.</value>
</data>
</root>
<data name="IgnoreConditionOnValueTypeInvalid" xml:space="preserve">
<value>The ignore condition 'JsonIgnoreCondition.WhenWritingNull' is not valid on value-type member '{0}' on type '{1}'. Consider using 'JsonIgnoreCondition.WhenWritingDefault'.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ namespace System.Text.Json.Serialization
{
/// <summary>
/// When specified on <see cref="JsonSerializerOptions.DefaultIgnoreCondition"/>,
/// <see cref="WhenWritingDefault"/> specifies that properties with default values are ignored during serialization.
/// determines when properties and fields across the type graph are ignored.
/// When specified on <see cref="JsonIgnoreAttribute.Condition"/>, controls whether
/// a property is ignored during serialization and deserialization.
/// a property is ignored during serialization and deserialization. This option
/// overrides the setting on <see cref="JsonSerializerOptions.DefaultIgnoreCondition"/>.
/// </summary>
public enum JsonIgnoreCondition
{
Expand All @@ -21,7 +22,13 @@ public enum JsonIgnoreCondition
Always = 1,
/// <summary>
/// If the value is the default, the property is ignored during serialization.
/// This is applied to both reference and value-type properties and fields.
/// </summary>
WhenWritingDefault = 2,
/// <summary>
/// If the value is <see langword="null"/>, the property is ignored during serialization.
/// This is applied only to reference-type properties and fields.
/// </summary>
WhenWritingNull = 3,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,29 +125,47 @@ private void DetermineSerializationCapabilities(JsonIgnoreCondition? ignoreCondi
}
}

private void DetermineIgnoreCondition(JsonIgnoreCondition? ignoreCondition, bool isReferenceType)
private void DetermineIgnoreCondition(JsonIgnoreCondition? ignoreCondition, bool defaultValueIsNull)
{
if (ignoreCondition != null)
{
Debug.Assert(MemberInfo != null);
Debug.Assert(ignoreCondition != JsonIgnoreCondition.Always);

if (ignoreCondition != JsonIgnoreCondition.Never)
if (ignoreCondition == JsonIgnoreCondition.WhenWritingDefault)
{
Debug.Assert(ignoreCondition == JsonIgnoreCondition.WhenWritingDefault);
IgnoreDefaultValuesOnWrite = true;
}
else if (ignoreCondition == JsonIgnoreCondition.WhenWritingNull)
{
if (defaultValueIsNull)
{
IgnoreDefaultValuesOnWrite = true;
}
else
{
ThrowHelper.ThrowInvalidOperationException_IgnoreConditionOnValueTypeInvalid(this);
}
}
}
#pragma warning disable CS0618 // IgnoreNullValues is obsolete
else if (Options.IgnoreNullValues)
{
Debug.Assert(Options.DefaultIgnoreCondition == JsonIgnoreCondition.Never);
if (isReferenceType)
if (defaultValueIsNull)
{
IgnoreDefaultValuesOnRead = true;
IgnoreDefaultValuesOnWrite = true;
}
}
else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull)
{
Debug.Assert(!Options.IgnoreNullValues);
if (defaultValueIsNull)
{
IgnoreDefaultValuesOnWrite = true;
}
}
else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault)
{
Debug.Assert(!Options.IgnoreNullValues);
Expand All @@ -164,11 +182,11 @@ private void DetermineIgnoreCondition(JsonIgnoreCondition? ignoreCondition, bool
public abstract bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer);
public abstract bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter writer);

public virtual void GetPolicies(JsonIgnoreCondition? ignoreCondition, bool isReferenceType)
public virtual void GetPolicies(JsonIgnoreCondition? ignoreCondition, bool defaultValueIsNull)
{
DetermineSerializationCapabilities(ignoreCondition);
DeterminePropertyName();
DetermineIgnoreCondition(ignoreCondition, isReferenceType);
DetermineIgnoreCondition(ignoreCondition, defaultValueIsNull);
}

public abstract object? GetValueAsObject(object obj);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public override void Initialize(
}
}

GetPolicies(ignoreCondition, isReferenceType: default(T) == null);
GetPolicies(ignoreCondition, defaultValueIsNull: Converter.CanBeNull);
}

public override JsonConverter ConverterBase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@ public bool IgnoreNullValues

if (value && _defaultIgnoreCondition != JsonIgnoreCondition.Never)
{
Debug.Assert(_defaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault);
throw new InvalidOperationException(SR.DefaultIgnoreConditionAlreadySpecified);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@ public static void ThrowInvalidOperationException_JsonIncludeOnNonPublicInvalid(
throw new InvalidOperationException(SR.Format(SR.JsonIncludeOnNonPublicInvalid, memberInfo.Name, parentType));
}

[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowInvalidOperationException_IgnoreConditionOnValueTypeInvalid(JsonPropertyInfo jsonPropertyInfo)
{
MemberInfo memberInfo = jsonPropertyInfo.MemberInfo!;
throw new InvalidOperationException(SR.Format(SR.IgnoreConditionOnValueTypeInvalid, memberInfo.Name, memberInfo.DeclaringType));
}

[DoesNotReturn]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowNotSupportedException_ObjectWithParameterizedCtorRefMetadataNotHonored(
Expand Down
Loading

0 comments on commit 9b3cbc4

Please sign in to comment.