I’m experiencing an inexplicable exception when instantiating a JsonSerializerOptions object with a custom converter.
Test conditions:
- Compiled library in C#.
- Make a call from my library in a GH C# node which instantiates a custom JsonConverterFactory in the JsonSerializerOptions.Converters.
- Custom JsonConverterFactory instanitates without problems. Exception thrown is immediately after instantiation of the JsonSerializerOptions object.
Exception: System.ArrayTypeMismatchException: ‘Attempted to access an element as a type incompatible with the array.’
Other info in VS logs: Exception thrown: ‘System.ArrayTypeMismatchException’ in mscorlib.dll.
Notes: this is not a deserialization issue - i.e. its not a malformed JSON file which is throwing this exception. The code never reaches deserialization since the exception is thrown when the JsonSerializerOptions object is instantiated.
There is nothing in the custom JsonConverterFactory which can throw this exception either (see code below).
I should add the code is async so I’m not sure if this error is a red herring and perhaps the way the GH C# code generator behind the scenes is unable to support async code?
Also, this same call works absolutely fine when running in Revit using RiR to make the call (this is actually the natural home of said method). Its the first time I’ve seen this exception having been running this same code in a Revit addin via RiR for the past 6 months without issue. It was only after calling said code in GH via the C# node do I see this exception.
Code snipper where exception is thrown:
var serializerOptions = new JsonSerializerOptions
{
Converters = {
new JsonStringEnumConverter(),
new InterfaceConverterFactory(typeof(OverrideData), typeof(IOverrideData)),
}
};
Custom converter code:
/// <summary>
/// A <see cref="JsonConverterFactory"/> which is used to inject concrete
/// types into interface declarations for the <see cref="JsonSerializer"/>.
/// </summary>
public class InterfaceConverterFactory : JsonConverterFactory
{
/// <summary>
/// The concrete type to inject.
/// </summary>
public Type ConcreteType { get; }
/// <summary>
/// The interface which the <see cref="ConcreteType"/> implements.
/// </summary>
public Type InterfaceType { get; }
/// <summary>
/// Creates a new <see cref="InterfaceConverterFactory"/>.
/// </summary>
public InterfaceConverterFactory(Type concrete, Type interfaceType)
{
this.ConcreteType = concrete;
this.InterfaceType = interfaceType;
}
/// <summary>
/// Returns true if the <see cref="ConcreteType"/> is a <see cref="InterfaceType"/>.
/// </summary>
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert == this.InterfaceType;
}
/// <summary>
/// Instantiates the required <see cref="JsonConverter"/> to deserialize
/// to an interface type using a concretion.
/// </summary>
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var converterType = typeof(InterfaceConverter<,>).MakeGenericType(this.ConcreteType, this.InterfaceType);
return (JsonConverter)Activator.CreateInstance(converterType);
}
}