Suppose we have the following code:
Type t = typeof(UInt64);
var def = Activator.CreateInstance(t);
Console.WriteLine(def.GetType());
string json = "18446744073709551615";
object parsedObject = JsonConvert.DeserializeAnonymousType(json, def);
Console.WriteLine(parsedObject.GetType());
The output is:
System.UInt64
System.Numerics.BigInteger
Since I explicitly fed DeserializeAnonymousType
with def
, type of which is UInt64
, I would expect also UInt64
as an output, especially since 18446744073709551615 is a valid UInt64
value (max value, granted, but I checked also with 18446744073709551614, it is same).
Why is it so? I checked Newtonsoft Github issues, and found nothing (at least, not in open issues).
How can I force the correct type which I know in advance (dynamically, I have only System.Type
)? Obviously, if it happens only for UInt64
I can make a check and cast explicitly.
Your problem is that JsonConvert.DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
doesn't quite do what you expect. It doesn't deserialize the JSON string to the actual type of the T anonymousTypeObject
argument. It deserializes the JSON string to the declared type of the argument -- which in your case, is object
.
This can be seen from the reference source:
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{
return DeserializeObject<T>(value);
}
The T anonymousTypeObject
is never actually used. Instead the target type is entirely specified via type inference when the call to DeserializeAnonymousType
is made -- specifically from the declared type of the variable def
in your code. But def
is implicitly declared to be an object
, because that is what Activator.CreateInstance(Type type)
is declared to return. Thus object
is what Json.NET deserializes the JSON as -- some .Net type sufficient to capture the incoming JSON. As BigInteger
is sufficient to capture the incoming JSON, Newtonsoft happens to choose that type instead of Uint64
.
if you want to force Json.NET to deserialize to the actual, concrete type of a specific object, use JsonConvert.DeserializeObject(string value,Type type)
:
object parsedObject = JsonConvert.DeserializeObject(json, def.GetType());
Demo fiddle here.