While doing a code review I noticed the following comment on a public property of a message contract class:
/// <summary> | |
/// Property used internally for mapping, cannot and should not be passed along externally. | |
/// </summary> | |
/// Ideal solution would be to make it internal, but System.Text.Json does not serialize private or internal properties. |
Although I have other concerns about the design of this class and why this property should not be part about this message contract, I want to focus on the comment itself. Starting from .NET 7, the comment is no longer correct and you CAN serialize private (and internal) properties.
It does not work out of the box(the default still is to ignore private fields and properties), but the necessary extension points are in place to change this behavior. The way to do this is by writing your own Modifier.
A modifier is an Action<JsonTypeInfo>
or a method with a JsonTypeInfo parameter that gets the current state of the contract as an argument and makes modifications to the contract.
Serialize internal properties
Let us create an example modifier that allows the serialization of internal properties.
We first create our modifier method:
void AddInternalPropertiesModifier(JsonTypeInfo jsonTypeInfo) | |
{ | |
if (jsonTypeInfo.Kind != JsonTypeInfoKind.Object) | |
return; | |
foreach (PropertyInfo property in jsonTypeInfo.Type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)) | |
{ | |
JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(property.PropertyType, property.Name); | |
jsonPropertyInfo.Get = property.GetValue; | |
jsonPropertyInfo.Set = property.SetValue; | |
jsonTypeInfo.Properties.Add(jsonPropertyInfo); | |
} | |
} |
To use this modifier we need to specify it as a part of our JsonSerializerOptions
:
var options = new JsonSerializerOptions | |
{ | |
TypeInfoResolver = new DefaultJsonTypeInfoResolver | |
{ | |
Modifiers = { AddInternalPropertiesModifier } | |
} | |
}; | |
var person = new Person{LastName="Wullems", FirstName="Bart"}; | |
string json = JsonSerializer.Serialize(person, options); |
If you want to learn more and see some other examples, have a look at the documentation here: Custom serialization and deserialization contracts | Microsoft Learn