Matthias Burger
Matthias Burger

Reputation: 5946

Dynamically deserialize a JSON to acces its generic type

I'm trying to deserialize an configuration-JSON dynamically to an object.

The JSON is a combination of a base and a custom for each service I want to configure.

one config looks like

{
    "_clr": "MyNamespace.Models.Admin.MailServiceConfig, Assembly",
    "configuration": {
        "mailWarning": 120
    }

}

the only thing what changes is the content of "configuration" (another service has another configuration with more properties with more levels)

So the classes for deserializing would look like this:

public class ServiceConfiguration
{
    [JsonProperty("_clr")]
    public string Clr { get; set; }
    [JsonIgnore]
    public IServiceValidation Configuration { get; set; }
}

public interface IServiceValidation
{
    bool ThrowError();
}

public class ExtraConfiguration<T>: ServiceConfiguration where T: IServiceValidation
{
    [JsonProperty("configuration")]
    public new T Configuration { get; set; }
}

My target is to deserialize to ServiceConfiguration to get Clr - with this info I would deserialize a second time to ServiceConfiguration<[Clr]>.

I wrote the method for this:

private ServiceConfiguration _getConfiguration(string configuration)
{
    ServiceConfiguration config = JsonConvert.DeserializeObject<ServiceConfiguration>(configuration);
    string className = config.Clr; // classname must be "Namespace.MyClass, MyAssembly"

    Type baseType = typeof(ExtraConfiguration<>);
    Type[] typeArgs = {Type.GetType(className)};

    Type genericType = baseType.MakeGenericType(typeArgs);

    return (ServiceConfiguration)JsonConvert.DeserializeObject(configuration, genericType);
}

This returns the casted object - the problem is, I want to access the property Configuration which is now T as IServiceValidation to execute ThrowError(). But when I try to access, Configuration is null.

When debugging, I can see, there are now two Configuration-Properties. One is null and one has the object I want - any idea how I can access the second one as IServiceValidation?enter image description here

Upvotes: 0

Views: 69

Answers (1)

Amir Popovich
Amir Popovich

Reputation: 29836

I would take a different approach. Fetch the type from the json, fetch the config json from the original json and create the dynamic service validator from it.

var configuration = @"{
                ""_clr"": ""Playground.MailServiceConfig, Playground"",
                ""configuration"": {
                        ""mailWarning"": 120
                }
            }";

var configurationJson = JObject.Parse(configuration);
var type = Type.GetType(configurationJson["_clr"].Value<string>());
var config = configurationJson["configuration"] as JObject;
var serviceValidation = config.ToObject(type) as IServiceValidation;

Upvotes: 1

Related Questions