Json.net DeserializeAnonymousType возвращает BigInteger вместо UInt64 - PullRequest
1 голос
/ 04 мая 2019

Предположим, у нас есть следующий код:

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());

Вывод:

System.UInt64 
System.Numerics.BigInteger

Так как я явно указывал DeserializeAnonymousType с def, типом которого является UInt64, я ожидал бы также UInt64 в качестве вывода, тем более что 18446744073709551615 является действительным значением UInt64 (максимальное значение предоставлено, но я проверил также с 18446744073709551614, это то же самое).

Почему это так? Я проверил проблемы Newtonsoft Github и ничего не нашел (по крайней мере, не в открытых проблемах).

Как я могу форсировать правильный тип, который я знаю заранее (динамически, у меня есть только System.Type)? Очевидно, что если это происходит только для UInt64, я могу сделать проверку и привести в явном виде.

1 Ответ

2 голосов
/ 04 мая 2019

Ваша проблема в том, что JsonConvert.DeserializeAnonymousType<T>(string value, T anonymousTypeObject) не совсем то, что вы ожидаете. Он не десериализует строку JSON в фактический тип аргумента T anonymousTypeObject. Он десериализует строку JSON в объявленный тип типа аргумента - в вашем случае это object.

Это видно из справочного источника :

public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{
    return DeserializeObject<T>(value);
}

T anonymousTypeObject фактически никогда не используется. Вместо этого целевой тип полностью указывается с помощью вывода типа, когда выполняется вызов DeserializeAnonymousType, в частности, из объявленного типа переменной def в вашем коде. Но def неявно объявляется как object, потому что это то, что Activator.CreateInstance(Type type) объявлено возвращаемым. Таким образом, object - это то, что Json.NET десериализует как JSON - некоторый тип .Net, достаточный для захвата входящего JSON. Поскольку BigInteger достаточно для захвата входящего JSON, Newtonsoft выбирает этот тип вместо Uint64.

, если вы хотите принудительно десериализовать Json.NET для конкретного конкретного типа конкретного объекта, используйте JsonConvert.DeserializeObject(string value,Type type):

object parsedObject = JsonConvert.DeserializeObject(json, def.GetType());

Демонстрационная скрипка здесь .

...