-
Notifications
You must be signed in to change notification settings - Fork 5k
Add json deserialize interface attribute to specific class #63436
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
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json Issue DetailsFor me, having a lot of classes with
Perhaps this already is implemented, however I can't seem to find the documentation for it, even after quite some searching.
|
@eiriktsarpalis this seems like a design consideration for the polymorphic serialization feature - #30083. |
Note that since serialization is not covariant this only really works well for deserialization. For serialization there is a good chance of you getting a runtime cast error, if the value of the serialized property is not of type Nevertheless, it should still be possible to define your own using System;
using System.Text.Json;
using System.Text.Json.Serialization;
string json = JsonSerializer.Serialize<Foo>(new Bar { A = 1, B = 2 });
Bar bar = (Bar)JsonSerializer.Deserialize<Foo>(json)!;
Console.WriteLine(bar.B);
[JsonHandleAs(typeof(Bar))]
public class Foo
{
public int A { get; set; }
}
public class Bar : Foo
{
public int B { get; set; }
}
public class JsonHandleAsAttribute : JsonConverterAttribute
{
private readonly Type _derivedType;
public JsonHandleAsAttribute(Type derivedType) => _derivedType = derivedType;
public override JsonConverter? CreateConverter(Type _) => new DerivedTypeConverter(_derivedType);
}
public class DerivedTypeConverter : JsonConverterFactory
{
private readonly Type _derivedType;
public DerivedTypeConverter(Type derivedType) => _derivedType = derivedType;
public override bool CanConvert(Type typeToConvert)
// NB check doesn't cover interface implementations which require more involved reflection.
// Interface support left as exercise to the reader.
=> typeToConvert != _derivedType && typeToConvert.IsAssignableFrom(_derivedType);
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var converterType = typeof(DerivedTypeConverter<,>).MakeGenericType(_derivedType, typeToConvert);
return (JsonConverter)Activator.CreateInstance(converterType, options)!;
}
}
public class DerivedTypeConverter<TDerived, TBase> : JsonConverter<TBase>
where TDerived : TBase
{
private readonly JsonConverter<TDerived> _derivedConverter;
public DerivedTypeConverter(JsonSerializerOptions jsonSerializerOptions)
{
_derivedConverter = (JsonConverter<TDerived>)jsonSerializerOptions.GetConverter(typeof(TDerived));
}
public override TBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Type-safe upcast to TBase
return _derivedConverter.Read(ref reader, typeof(TDerived), options);
}
public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options)
{
// Downcast can fail at runtime!
_derivedConverter.Write(writer, (TDerived)value!, options);
}
} |
Thanks a lot @eiriktsarpalis ! |
@eiriktsarpalis : I am fairly new to this.. but would it be possible to tweak your code above to work with serialization of the following snippet:
When I try this I get the following exception:
|
@erikthysell that's not supported, but the request is tracked by a separate issue #54189. |
For me, having a lot of classes with
interface
s, it would be nice with a simple property attribute for deserialization to a specific concrete class, instead of having to write custom converters each time.I.e. I propose something along this :
Perhaps this already is implemented, however I can't seem to find the documentation for it, even after quite some searching.
The text was updated successfully, but these errors were encountered: