I want to use polymorphic JSON for the RichText type in .NET 10 because I plan migrating from one richtext format to another and I am stuck with a problem: when the object is automatically serialized when being sent to a client, everything is fine, the type discriminator is present and everything works.
But when serizlizing it to store in the database, it does include the type discriminator in the resulting JSON, but at the end, not in the beginning. As you know, it is an issue when deserializing back because .NET requires the discriminator to be the first field in the JSON.
Here is the interface type:
[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type")]
[JsonDerivedType(
derivedType: typeof(DeltaRichText),
typeDiscriminator: DeltaRichText.TypeDiscriminator
)]
public interface IRichTextType;
And here one of the implementations (currently I only have one):
public class DeltaRichText : IRichTextType
{
public const string TypeDiscriminator = "delta";
[Required]
[MinLength(1)]
[JsonPropertyName("ops")]
public List<DeltaOp> Ops { get; set; } = [];
/// <summary>
/// Default constructor for DeltaRichText.
/// Initializes the Ops property with an empty DeltaOp.
/// </summary>
public DeltaRichText()
{
Ops = [DeltaOp.Empty()];
}
public override string? ToString()
{
return JsonSerializer.Serialize<IRichTextType>(this);
}
// some other code...
}
Then, I added a converter in the DbContext:
new ValueConverter<IRichTextType?, string?>(
v => v == null ? null : v.ToString(),
v => v == null ? null : JsonSerializer.Deserialize<IRichTextType>(v, JsonSerializerOptions.Web)
);
Things I tried that do not work:
- add polymorphic attributes to the derived types (in this case the DeltaRichText) too
- adding manually the
Typeproperty to every derived type with[JsonPropertyName('$type')]and[JsonPropertyOrder(-1)]
It seems it can be solved by creating a custom converter or by creating a Dictionary<string, object?> with the correct order manually and then serializing it. But it seems too much for such an issue and it does not solve it, but creates some huge workaround.
There is no problem when sending to the client, not to the database. I do not serizlize it myself but return it from the controller. In the Program.cs, I do not add some extra json properties or customization. In the DBContext, I use JsonSerializerOptions.Web, but it does not work with any of the options available.
AllowOutOfOrderMetadataProperties = truein the JsonSerializerOptions. But this is not ideal since some parsers and apps rely on the metadata properties to be firstValueConverter<IRichTextType?, string?>and callConvertToProvideron anIRichTextType iRichText = new DeltaRichText();instance, the"$type"parameter is emitted first. See dotnetfiddle.net/rxQsd0. Is there any chance that your database might be shredding and re-ordering the properties? Or that, when you fetch the JSON value from the database, you are selecting them in such a way that they are reordered?