_Updated by @layomia. I'm pasting the API approved in https://github.com/dotnet/runtime/issues/35649, along with API review notes. An option to ignore defaults on deserialization was not added, as we couldn't identify a reasonable scenario that requires this. This proposal does not include a way to specify a custom default. This is discussed in https://github.com/dotnet/runtime/issues/36236._
WhenWritingDefaultValues to WhenWritingDefault.JsonSerializerOptions.DefaultIgnoreCondition should throw ArgumentException rather than InvalidOperationException```C#
namespace System.Text.Json.Serialization
{
public enum JsonIgnoreCondition
{
Never = 0,
Always = 1,
WhenWritingDefault = 2
}
}
namespace System.Text.Json
{
public partial class JsonSerializerOptions
{
public JsonIgnoreCondition DefaultIgnoreCondition { get; set; } = JsonIgnoreCondition.Never;
}
}
<details>
<summary>
Original proposal (click to view)
</summary>
There is no option to ignore the `DefaultValues` for the properties in `System.Text.Json`.
The `JSON.NET` contains this options to ignore default values.
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DefaultValueHandling.htm
**Usecase scenario:**
For updating the Blazor component model, need to send the values which has only changes to component and refresh the UI, even for initial rendering of component itself, we will the default values.
```csharp
return JsonSerializer.ToString(this, this.GetType(), new JsonSerializerOptions
{
IgnoreNullValues = true,
WriteIndented = true
});
Currently there is no support for Ignoring Default Values while Serialization in System.Text.Json, which is required for ignoring default value for value types (Data type), as mentioned earlier by @karthickthangasamy the same support is available in Json.NET, this can be achieved by adding an API IgnoreDefaultValues to the Json Serializer Options and then validating a condition to check if the IgnoreDefaultValues API is set true and the value is default value before serializing only for the value types since it cannot be provided for reference types.
IgnoreDefaultValues API is proposed similar to existing API IgnoreNullValues
/// <summary>
/// Determines whether default values are ignored during serialization and deserialization.
/// The default value is false.
/// </summary>
/// <exception cref="InvalidOperationException">
/// Thrown if this property is set after serialization or deserialization has occurred.
/// </exception>
public bool IgnoreDefaultValues
{
get
{
return _ignoreDefaultValues;
}
set
{
VerifyMutable();
_ignoreDefaultValues = value;
}
}
bool includeProperty = true;
// Check default value property.
if (options.IgnoreDefaultValues)
{
DefaultValueAttribute defaultValueAttribute = JsonPropertyInfo.GetAttribute<DefaultValueAttribute>(jsonPropertyInfo.PropertyInfo);
currentValue = jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue);
includeProperty = (defaultValueAttribute != null && object.Equals(currentValue, defaultValueAttribute.Value)) == false;
}
if (includeProperty)
{
jsonPropertyInfo.Write(ref state, writer);
}
IgnoreDefaultValues for getting input from user if default values are to be ignored while JSON serialization using JsonSerializerOptions in System.Text.Json.A PR with the proposed changes is available: #42288
@layomia following on from https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md, who is the owner of this suggestion? Is there anything we can we do to help move this through discussion?
From @SanderSade in https://github.com/dotnet/runtime/issues/681:
JSON.NET has DefaultValueHandling enumeration, which allows users to determine how the default values are handled during de/serialization.
Similar functionality would be very useful in System.Text.Json, as DefaultValueHandling.Ignore/IgnoreAndPopulate would allow considerable reduction of JSON size in many cases.
@nickevansuk we are planning for 5.0 and this issue is being discussed. The next step is to create a formal API proposal. The proposal should include API modifications, rationale, usage scenarios and code examples, and raise any open questions. This would be a good way to help move this along. Here is an example of a good one: https://github.com/dotnet/corefx/issues/4547#issue-117426449.
This proposal should be added to this thread, and we'll merge it into the description of this issue for greater visibility. I'll own the feature and drive it through framework core API review.
Some things to consider for this issue:
JsonIgnoreCondition enum being proposed in https://github.com/dotnet/corefx/issues/40600), or both?DefaultValueAttribute in System.ComponentModel be used, or should System.Text.Json implement a new one. Plays into the larger question of whether S.T.Json should use external attributes.JsonPropertyAttribute which could contain properties like DefaultValue, IgnoreCondition, and prevent numerous attributes being added to satisfy other features (e.g. something like JsonIncludeAttribute to support properties with non-public setter/getters - https://github.com/dotnet/corefx/issues/38163).default(typeof(PropertyInQuestion)) if none is provided.Regarding:
"granularity: should the option be global (on JsonSerializerOptions), per-property (probably leveraging the JsonIgnoreCondition enum being proposed in dotnet/corefx#40600), or both?"
If the granularity is per-property, this could probably be used to solve:
https://github.com/dotnet/runtime/issues/512
Is there an ETA for this feature in an upcoming release? My JSON class has many bools and it would be nice to default them all to false which would greatly reduce the serialized size.
Don't want to point out obvious but for the time being one can make value type fields nullable and use IgnoreNullValues = true to get around this limitation.
Don't want to point out obvious but for the time being one can make value type fields nullable and use
IgnoreNullValues = trueto get around this limitation.
Yes I did consider this. My models are used with a Razor engine application and bool? will not bind to checkboxes unfortunately.
in progress ... woot !
I updated the issue description with API approved in https://github.com/dotnet/runtime/issues/35649. Specifying a custom default is discussed in https://github.com/dotnet/runtime/issues/36236.
Currently, with WhenWritingDefault, it doesn't serialize, for instance, int type with the default value. There's should be an option to skip nullable types but still serialize non-nullable types. I don't need to receive anything in JSON that is null but I do want to receive fields with values of 0. In JavaScript apps, having something undefined or 0 makes a big difference. In a nutshell, WhenWritingDefault makes int fields of 0 to become undefined in JavaScript client. For now, I use int? instead of int as a workaround which is not a good solution.
I ran into the same issue as @rubo when updating my app to .NET 5. The current JsonIgnoreCondition.WhenWritingDefault is a breaking change that feels a little too strong. Would it be possible to add a JsonIgnoreCondition.WhenNull that skips null values but writes defaults like 0 and false? This comment indicates that JsonIgnoreCondition.WhenNull was removed - why is that?
For context, my app implements the NuGet protocol. This protocol requires some integer and boolean properties even if they have default values (for example, the search API must return a downloads value even if a package has 0 downloads). However, this protocol also has optional properties that should be omitted if they have a value of null (for example, the package metadata API should omit the deprecation property if a package is not deprecated). Adding JsonIgnoreAttributes everywhere as needed is rather inconvenient.
@rubo, @loic-sharma this will be addressed with https://github.com/dotnet/runtime/issues/39152.
Most helpful comment
@rubo, @loic-sharma this will be addressed with https://github.com/dotnet/runtime/issues/39152.