在測驗在 .Net 6.0 中創建的 av web API 時,我們發現當 API 的用戶在 int 上發送十進制數時,您會收到 400 錯誤,指出由于 int 值上的小數,它無法決議 json。但是對長值做同樣的事情效果很好,它只是洗掉了十進制數字。
因此,為了測驗這是否(猜測 MS 使用 Newonsoft.Json),我制作了一個小 cmd 測驗應用程式來測驗場景。同樣的事情也發生在那里 long pareses 失去小數,并且 int 失敗。
那么這是決議器中的錯誤還是設計錯誤?[編輯] 應該不會也長期失敗吧?
using Newtonsoft.Json;
var data = JsonConvert.DeserializeObject<SomData>(@"{""aInt"":1, ""ALong"":2.2}");
Console.WriteLine(data.ALong); // output 2
var data2 = JsonConvert.DeserializeObject<SomData>(@"{""aInt"":1.2, ""ALong"":2}"); // exception
Console.WriteLine(data2.AInt);
internal class SomData
{
public int AInt { get; set; }
public long ALong { get; set; }
}
uj5u.com熱心網友回復:
答案是設計使然。我們可以在 Web API #654 中看到這個討論錯誤將浮點值轉換為整數。作者的回答如下。
將浮點值反序列化為整數屬性時,更高版本的 Json.NET 會引發錯誤。
decimal
當您使用浮點數時,我總是會使用。
internal class SomData
{
public decimal AInt { get; set; }
public decimal ALong { get; set; }
}
編輯
我看過 Json.Net 的源代碼
Int 值將else
作為 ReadType.ReadAsInt32 中JsonTextReader中的以下代碼的一部分
正如作者設計的那樣。
ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out int value);
if (parseResult == ParseResult.Success)
{
numberValue = value;
}
else if (parseResult == ParseResult.Overflow)
{
throw ThrowReaderError("JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
但是讓我們看看ReadType.ReadAsInt64之間的那else
部分有很多不同ReadAsInt32
。
首先,它將else
讓 value( object
type) 存盤為浮點值,如下面的代碼。
ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out long value);
if (parseResult == ParseResult.Success)
{
numberValue = value;
numberType = JsonToken.Integer;
}
else if (parseResult == ParseResult.Overflow)
{
#if HAVE_BIG_INTEGER
string number = _stringReference.ToString();
if (number.Length > MaximumJavascriptIntegerCharacterLength)
{
throw ThrowReaderError("JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
numberValue = BigIntegerParse(number, CultureInfo.InvariantCulture);
numberType = JsonToken.Integer;
#else
throw ThrowReaderError("JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
#endif
}
else
{
if (_floatParseHandling == FloatParseHandling.Decimal)
{
parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal d);
if (parseResult == ParseResult.Success)
{
numberValue = d;
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
}
else
{
string number = _stringReference.ToString();
if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double d))
{
numberValue = d;
}
else
{
throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
}
}
numberType = JsonToken.Float;
}
然后數字將由JsonSerializerInternalReader.EnsureType轉換為 Int64
// this won't work when converting to a custom IConvertible
return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
所以我們可以得到long
不會得到執行但int
會,不知道為什么ReadAsInt64
允許存盤為浮動但int
不是。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/456306.html