-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More extensible object and collection converters #36785
Comments
Moving to future. There are three aspects to this issue that overlap, so we want a single, consistent model to cover these:
|
Please at least support writing custom converter for |
Moving to 7.0 for consideration of remaining features. |
For
see the proposal by @eiriktsarpalis in #55781 (comment) |
In #31257, it's hinted that the OnSerialzing methods from #39896 would be helpful in ignoring properties at run time, but I'm not seeing how this behavior would work. Specifically, I need to exclude a collection during serialization only when it's empty. I have a custom collection class [JsonConverter(typeof(LinkCollectionConverter))]
public sealed class LinkCollection : IEnumerable<KeyValuePair<string, Link>>, IEnumerable
{
public static readonly LinkCollection Empty = new(new Dictionary<string, Link>());
// omitted for brevity
} and the associated converter public class LinkCollectionConverter : JsonConverter<LinkCollection>
{
public override bool HandleNull => false;
public override LinkCollection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Dictionary<string, Link>? value = JsonSerializer.Deserialize<Dictionary<string, Link>>(ref reader, options);
return new LinkCollection(value);
}
public override void Write(Utf8JsonWriter writer, LinkCollection value, JsonSerializerOptions options)
{
if (value is not null && value.Count > 0)
{
writer.WriteStartObject();
foreach (KeyValuePair<string, Link> pair in value)
{
writer.WritePropertyName(pair.Key);
JsonSerializer.Serialize(writer, pair.Value, options);
}
writer.WriteEndObject();
}
}
} The POCO using this collection looks like public class LicenseName
{
[JsonPropertyName("name")]
[JsonInclude]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string? Name { get; set; }
[JsonPropertyName("_links")]
[JsonInclude]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public LinkCollection? Links { get; init; } = null;
} Although this works, what I really want is for the property in the POCO to be this [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public LinkCollection Links { get; init; } = LinkCollection.Empty(); A serialized instance should look like {"name":"test"} The problem is that when I define my property as I want (with it initialized to an empty collection rather than null), I end up with JSON that looks like {"name":"test", "_links": } which isn't valid JSON. I really need a way to prevent the property from being written at all when it's empty. Is this possible with the state of STJ in .NET 6? I've tried implementing When I deserialize into an instance, it should populate the What would be really nice is if there were an additional |
I might have found a solution for this, but it is a bit ugly since you need to implement the IJsonOnSerializing interface in every single class you want to serialize without empty collections. You basically set all empty collections to null before the serializer kicks in. This way the ignore condition is honored and the property is not serialized.
Produces the following output: {"Name":"Test"} In my case, all classes are reverse engineered from a database schema, so I could easily generate the code with custom handlebar templates. So far the JSON response of my API was often quite big just because of the empty collections, since most classes had several navigation properties. If I load 50 entities of one of my main tables, the JSON response is now only 23kB instead of 111kB which is just 1/5th. So for me this seems to work, but if you cannot generate the classes automatically, it is a pain to edit everything manually. It is also improving performance and (logically) allocations! Serializing Product class with/without IJsonOnSerializing interface:
Serializing with source generator context:
Serializing Product class with three instead of one property of type ICollection:
Serializing Product class with three instead of one property of type ICollection and source generator context:
|
This is the new issue to add a public object\POCO converter. The previous issue was #1562 which was re-purposed for a refactoring effort and subsequently closed.
API proposal to come soon. It is expected to address several issues to make authoring converters for POCOs much easier and also be leveraged by a code-gen (AOT) effort that is in progress.
See 5.0 serializer goals for high-level information on the code-gen effort.
Work
The text was updated successfully, but these errors were encountered: