Json.NET将序列化
float
使用往返精度格式的值
"R"
(
source
). 但是,你使用的类型,
https://github.com/FNA-XNA/FNA/blob/master/src/Vector2.cs
,有一个
TypeConverter
应用:
[Serializable]
[TypeConverter(typeof(Vector2Converter))]
[DebuggerDisplay("{DebugDisplayString,nq}")]
public struct Vector2 : IEquatable<Vector2>
{
//...
如中所述
Newtonsoft docs
,此类类型将使用转换器序列化为字符串:
基本类型
.Net版本:
类型转换器
(可转换为字符串)
JSON:字符串
并且,检查代码
https://github.com/FNA-XNA/FNA/blob/master/src/Design/Vector2Converter.cs
,此转换器似乎是
不
转换为字符串时使用往返精度格式,在
around line 60
:
return string.Join(
culture.TextInfo.ListSeparator,
new string[]
{
vec.X.ToString(culture),
vec.Y.ToString(culture)
}
);
因此,内置
类型转换器
它本身就是你失去精确性的地方。
为了避免这个问题,你可以
-
创建
custom
JsonConverter
对于
Vector2
例如:
public class Vector2Converter : JsonConverter
{
class Vector2DTO
{
public float X;
public float Y;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Vector2) || objectType == typeof(Vector2?);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// A JSON object is an unordered set of name/value pairs so the converter should handle
// the X and Y properties in any order.
var dto = serializer.Deserialize<Vector2DTO>(reader);
if (dto == null)
return null;
return new Vector2(dto.X, dto.Y);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var vec = (Vector2)value;
serializer.Serialize(writer, new Vector2DTO { X = vec.X, Y = vec.Y });
}
}
如果将转换器添加到
JsonSerializerSettings.Converters
它将取代
类型转换器
.
工作样品小提琴
here
.
转换器序列化
二维向量
作为一个对象
X
和
Y
属性,但如果愿意,也可以将其序列化为具有两个值的数组。我不建议序列化为原始的
string
自从
二维向量
与JSON原语不对应。
-
使用
custom contract resolver
它不会为
类型转换器
应用,例如
Newtonsoft.JSON cannot convert model with TypeConverter attribute
.
笔记:
-
往返形式
“R”
显然不能保留
+0.0
和
-0.0
,因此Json.NET也没有,请参见
https://dotnetfiddle.net/aereJ2
或
https://dotnetfiddle.net/DwoGyX
为了演示。这个
Microsoft docs
在使用此格式时,不要提及是否应保留零符号。
因此,这是一个往返
浮动
可能导致二进制更改。
(多亏了
@chux
因为在年提出这个问题
comments
.)
-
另外,Json.NET还使用
“R”
写作时
double
(如
source for
JsonConvert.ToString(double value, ...)
):
internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
{
return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
}
为了
双重的
只有
记录此格式可能会丢失精度。从
The Round-trip ("R") Format Specifier
:
在某些情况下,如果使用
/platform:x64
或
/platform:anycpu
在64位系统上切换和运行。
因此往返
双重的
通过Json.NET可能会导致小的二进制差异。但是,这并不严格适用于这里的问题
浮动
.