Search code examples
c#arraysjsondynamicjil

Missing parameterless constructor when casting Jil dynamic deserialized object array


In our application we have a problem using a dynamic object, that is the result of JSON deserialization with Jil. The following code is just to show the problem.

void Main()
{
    var modelJson = "{\"Id\":1,\"Options\":[{\"Id\":2,\"Name\":\"Option 1\"}]}";
    var modelDto = Jil.JSON.DeserializeDynamic(modelJson);

    var options = modelDto.Options;
    var optionsIEnumerable = (IEnumerable<Option>)options;

    var optionsArray1 = optionsIEnumerable.ToArray();
    var optionsArray2 = optionsIEnumerable.Cast<Option>().ToArray();
}

class Model
{
    public Model(long id, IEnumerable<Option> options = null)
        : this()
    {
        this.Id = id;
        this.Options = options;
    }

    private Model() => this.Options = new List<Option>();

    public long Id { get; }

    public IEnumerable<Option> Options { get; }
}

class Option
{
    public Option(long id, string name)
    {
        this.Id = id;
        this.Name = name;
    }

    private Option()
    {
    }

    public long Id { get; private set; }

    public string Name { get; private set; }
}

The last two lines in Main both cause a MissingMethodException, saying there is no parameterless constructor. But both Model and Option have a parameterless constructor (and I am not even using Model at this point).

How can I cast the property modelDto.Options into a Option[]?


Solution

  • This is not the exact answer to your question but you could easily deserialize this JSON with the model.

    static void Main(string[] args)
    {
        var modelJson = "{\"Id\":1,\"Options\":[{\"Id\":2,\"Name\":\"Option 1\"}]}";
        var modelDto = Jil.JSON.Deserialize<ModelNew>(modelJson);
    
        ShowObject(modelDto);
        Console.Read();
    }
    
    class ModelNew
    {
        public int Id { get; set; }
        public  Option[] Options { get; set; }
        public ModelNew() {}
    }
    
    class Option
    {
        public long Id { get; private set; }
        public string Name { get; private set; }
        private Option() {}
    }
    

    Edit:

    To see the object use this function:

    static void ShowObject(ModelNew obj)
    {
        Console.WriteLine("Id: " + obj.Id);
        foreach (var op in obj.Options)
        {
            Console.WriteLine("Id: " + op.Id);
            Console.WriteLine("Name: " + op.Name);
        }
    }
    

    Output: Id: 1 Id: 2 Name: Option 1