Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing/deserializing System.Object using a different type

I would like to know how to implement a custom serializer/deserializer for the following class:

[JsonConverter(typeof(UnderlyingTypeConverter))]
public class ZoneProgramInput
{
    public string Name { get; set; }
    public Subject<object> InputSubject { get; }
    private IDisposable InputDisposable { get; set; }
    public Type Type { get; set; }
    public object Value { get; set; }
}

The requirement is that I would like to serialize/deserialize the property Value (of type object) with the type stored in the property Type and not with the type object. So if I have the following code:

var zpi = new ZoneProgramInput() { Type = typeof(System.Drawing.Color), Value = System.Drawing.Color.Red };
var serializedZpi = JsonConvert.SerializeObject(zpi);
var deserializedZpi = JsonConvert.DeserializeObject<ZoneProgramInput>(serializedZpi);

The variable deserializedZpi contains a deserialized instance of zpi, and the deserialized.Value should be of type System.Drawing.Color. Without a custom converter, it deserializes as a string rather than a System.Drawing.Color. As a note, I just chose System.Drawing.Color arbitrarily. This type can be anything.

I have a converter class called UnderlyingTypeConverter (which is set as the converter for ZoneProgramInput in the above code):

public class UnderlyingTypeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {

    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {

    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ZoneProgramInput);
    }
}

What should I fill into the ReadJson/WriteJson method to make sure that the Value property serializes and deserializes with the type stored in the Type property? I've tried looking around Google and StackOverflow for examples for ReadJson/WriteJson, but I haven't found anything that can help me find the type in this manner. Thank you for your help in advance.

PS: I know I could possibly use generics, but I already tried that. Making ZoneProgramInput take a generic type parameter and making Value of that type still serializes/deserializes Value as a string. I also tried using C# dynamic keyword and it's the same result. Also TypeNameHandling apparently doesn't work with things that are defined as object types. It just serializes them as strings instead of objects.

like image 311
Anshul Avatar asked May 14 '26 09:05

Anshul


1 Answers

It's kind of a shame that you need to do this, but I don't really see a way around it. Here's a converter that should work:

public class UnderlyingTypeConverter : JsonConverter
{
    public override void WriteJson(
        JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        var result = new ZoneProgramInput();

        // Deserialize into a temporary JObject
        JObject obj = serializer.Deserialize<JObject>(reader);

        // Populate the ZoneProgramInput object with the contents
        serializer.Populate(obj.CreateReader(), result);

        // Overwrite the "Value" property with the correct value based on the 
        // "Type" property.
        result.Value = 
            obj.GetValue("value", StringComparison.OrdinalIgnoreCase)
               .ToObject(result.Type, serializer);

        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ZoneProgramInput);
    }

    public override bool CanWrite
    {
        get { return false; }
    }
}

Example: https://dotnetfiddle.net/Zv57R8

like image 56
Andrew Whitaker Avatar answered May 16 '26 00:05

Andrew Whitaker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!