Raymond A.
Raymond A.

Reputation: 657

System.Text.Json.JsonException: 'Read unrecognized type discriminator id 'new-type'

I have a json document, that constantly increases the list of discriminators. My problem is that I can't get the "UnknownDerivedTypeHandling" to work. System.Text.Json and .net9.

// https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism
[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
[JsonDerivedType(typeof(RecordClass))]
[JsonDerivedType(typeof(RecordProfileClass), typeDiscriminator: "profile")]
[JsonDerivedType(typeof(RecordAccountClass), typeDiscriminator: "account")]

public class RecordClass
{
    [JsonPropertyName("$type")]
    public string RecordType { get; set; } = string.Empty;
    [JsonPropertyName("createdAt"), JsonRequired]
    public DateTime Created { get; set; }
}

public class RecordProfileClass : RecordClass
{
    [JsonPropertyName("description")]
    public string Description { get; set; } = string.Empty;
    [JsonPropertyName("displayName"), JsonRequired]
    public string DisplayName { get; set; } = string.Empty;
}
public class RecordAccountClass : RecordClass
{
    [JsonPropertyName("userprincipalname"), JsonRequired]
    public string UserPrincipalName{ get; set; } = string.Empty;
    [JsonPropertyName("objectId"), JsonRequired]
    public Guid ObjectId { get; set; } = Guid.Empty;
}

When I recieve json document and a "not listed" discriminator is used, the deserialization failes with the error:

System.Text.Json.JsonException: 'Read unrecognized type discriminator id 'guest'. Path: ...

What I was hoping for, was being able to fall back to base type if an unknown discriminator appeared with JsonUnknownDerivedTypeHandling.FallBackToBaseType

I have read Microsoft's page How to serialize properties of derived classes with System.Text.Json a several times, but I still don't get what I am doing wrong.

My JsonSerializerOptions

JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
{
    RespectNullableAnnotations = true,        
    WriteIndented = true
};

JsonSerializer.Deserialize<MessageClass>(messageJson, jsonOptions);

The MessageClass is a root class containing messageid, time, identities who "did the act", etc. My code:

public class MessageClass
{
    [JsonPropertyName("did"), JsonRequired]
    public string Did { get; set; } = string.Empty;
    [JsonPropertyName("time_us"), JsonRequired]
    public long Time_US { get; set; } = 0;
    [JsonPropertyName("commit")]
    public CommitClass? Commit { get; set; } = null;
    // There is more, but not relevant... 
}
public class CommitClass
{
    [JsonPropertyName("rev"), JsonRequired]
    public string Rev { get; set; } = string.Empty;
    [JsonPropertyName("operation"), JsonRequired]
    public string Operation { get; set; } = string.Empty;
    // There is more, but not relevant... 

   // THE BASE CLASS
    [JsonPropertyName("record")]
    public RecordClass? Record { get; set; }
}

I apologize if the code is messy, but it has been through a tennis match of a debugging session. And not all the editing of the code I did before writing this issue has been well thought out.

Upvotes: 2

Views: 132

Answers (1)

Guru Stron
Guru Stron

Reputation: 143098

JsonPolymorphicAttribute.UnknownDerivedTypeHandling is for serialization (as the corresponding enum). From the docs:

Gets or sets the behavior when serializing an undeclared derived runtime type.

You can use the JsonPolymorphicAttribute.IgnoreUnrecognizedTypeDiscriminators setting:

[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type", 
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType,
    IgnoreUnrecognizedTypeDiscriminators = true)]

Upvotes: 2

Related Questions