I have a number of JSON files each of which contains a list of different class objects.
I can work out the data class I'm expecting from the file's name and I have a generic JSON file reader which returns the correct data. However, I can't figure out how to assign that to anything in the calling method that allows me to access the results as the actual type.
I'm currently using this line:
var k = ReadJson<dynamic>(filePath, typeof(List<>).MakeGenericType(new[] { type }));
OR
var k = ReadJson<Object>(filePath, typeof(List<>).MakeGenericType(new[] { type }));
but they're both giving me
Unable to cast object of type 'System.Collections.Generic.List`1[Abc.Shared.Models.Location]' to type 'System.Collections.Generic.List`1[System.Object]'.
Conjecture: Since I can't call ReadJson directly can I call the ReadJson via reflection specifying the type of the generic 'T'? I've not been able work out if that's possible.
(For completeness here's the generic method - I don't think the problem is here though)
public static List<T> ReadJson<T>(string filePath, Type t) where T : class, new()
{
List<T> regions = new List<T>();
using (StreamReader file = System.IO.File.OpenText(filePath))
{
JsonSerializer serializer = new JsonSerializer();
regions = (List<T>)serializer.Deserialize(file, t);
}
return regions;
}
You can't cast List<T>
to List<TBase>
(and object
is base to all the reference types), because List<T>
isn't covariant. You can cast IEnumerable<T>
to IEnumerable<TBase>
, bacause IEnumerable<T>
is covariant. For historical reasons even arrays are covariant, so you can cast T[]
to TBase[]
. I'll give you both samples:
public static IEnumerable<T> ReadJson1<T>(string filePath, Type t) where T : class, new()
{
IEnumerable<T> regions = new List<T>();
using (StreamReader file = System.IO.File.OpenText(filePath))
{
JsonSerializer serializer = new JsonSerializer();
regions = (IEnumerable<T>)serializer.Deserialize(file, t);
}
return regions;
}
public static T[] ReadJson2<T>(string filePath, Type t) where T : class, new()
{
using (StreamReader file = System.IO.File.OpenText(filePath))
{
JsonSerializer serializer = new JsonSerializer();
var regions = (T[])serializer.Deserialize(file, t);
return regions;
}
}
Type type = typeof(MyObject);
IEnumerable<object> k1 = ReadJson1<object>("test.json", typeof(List<>).MakeGenericType(new[] { type }));
object[] k2 = ReadJson2<object>("test.json", type.MakeArrayType());