My Dto has Id
property:
public class ADto
{
public int Id { get; set; }
public string Text { get; set; }
}
The Id
is set by EF Core not by Frontend request, so I want to ignore it on deserialization ( but do not ignore on serialization, so already set Id by EF Core will be returned to Frontend), how to achieve that with attributes? I am using using System.Text.Json.Serialization;
.
Deserialization is done by ASP. NET Core, I need to implement it as an attribute.
There is no way to achieve exactly what you want with the attributes built in to System.Text.Json as of .NET 8 or earlier.
As a workaround, in .NET 7 and later you could create a custom attribute, then check for it in a custom typeInfo modifier when generating contracts for your types.
First define the following attribute:
[System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true)]
public sealed class JsonIgnoreOnDeserializationAttribute : System.Text.Json.Serialization.JsonAttribute
{
public static void Apply(JsonTypeInfo typeInfo)
{
if (typeInfo.Kind != JsonTypeInfoKind.Object)
return;
foreach (var property in typeInfo.Properties)
{
if (property.AttributeProvider?.IsDefined(typeof(JsonIgnoreOnDeserializationAttribute), true) == true)
property.Set = null;
}
}
}
And modify your type as follows:
public class ADto
{
[JsonIgnoreOnDeserialization]
public int Id { get; set; }
public string Text { get; set; }
}
Then, when setting up your serialization options, apply the modifier in .NET 8 by calling WithAddedModifier()
like so:
var options = new JsonSerializerOptions
{
// If you are using source generation, use SourceGenerationContext.Default here instead.
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
.WithAddedModifier(JsonIgnoreOnDeserializationAttribute.Apply),
// Add other options as required, e.g.:
WriteIndented = true,
};
Demo fiddle #1 here.
Notes:
The extension method WithAddedModifier()
is new in .NET 8 and allows for modification of contracts of arbitrary IJsonTypeInfoResolver
instances, including both both DefaultJsonTypeInfoResolver
and JsonSerializerContext
.
In .NET 7, use DefaultJsonTypeInfoResolver
and set the modifier explicitly:
var options = new JsonSerializerOptions
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers = { JsonIgnoreOnDeserializationAttribute.Apply },
},
// Add other options as required, e.g.:
WriteIndented = true,
};
Demo fiddle #2 here.
.NET 8 also has the ability to serialize properties that are entirely nonpublic, so you could consider modifying ADto
by marking Id
with [JsonIgnore]
and adding a private get-only surrogate property like so:
public class ADto
{
public ADto() { }
[JsonInclude, JsonPropertyName("Id")]
private int DeserializedId => Id;
[JsonIgnore]
public int Id { get; set; }
public string Text { get; set; }
}
In .NET 7 and earlier the surrogate property would need to be public, which you probably would not want.
Demo fiddle #3 here.