- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要反序列化原始二进制数据 (BinaryFormatter),然后序列化为 JSON(用于编辑),然后再次将其序列化回二进制。显然,我在花车上输了。当我从原始二进制(正确数据和中间数据在内存中为 1:1)序列化为 JSON。我知道这不是什么大损失,我知道 float 有问题,但由于以后可能出现的不兼容问题,我想尽可能保持精度。
有人用 JSON 解决过这个问题吗?如何强制它以最大精度写入 float ?我已经尝试将 float 处理为十进制或 double 的内置选项,但不幸的是,输出没有区别,而且我无法更改目标值,因为当我进行二进制序列化时,它们仍然需要写为 float ,所以会有舍入无论在隐式转换期间。
我尝试往返的包含 float 的特定类型是来自 https://github.com/FNA-XNA/FNA/blob/master/src/Vector2.cs 的 Vector2
.
tl:dr 有一个 float ,希望 JsonNET 尽可能精确地将它序列化为最终的 json 字符串。
附言我在这里阅读了大量问题,在其他地方阅读了博客条目,但没有发现任何人试图解决同样的问题,大多数搜索结果都与 float 阅读问题有关(我稍后也需要解决)。
更新:正如下面的 @dbc 指出的那样 - Jsont.NET 尊重“TypeConverter”属性,因此我必须制作自己的转换器来覆盖它。
最佳答案
Json.NET 将使用往返精度格式 "R"
( source ) 序列化 float
值。但是,您使用的类型 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 中所述,此类类型将使用转换器序列化为字符串:
Primitive Types
.Net:
TypeConverter
(convertible to String)
JSON: String
然后,检查 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)
}
);
因此内置的 TypeConverter
本身就是您失去精度的地方。
为了避免这个问题,你可以
创建 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
它将取代 TypeConverter
。
工作样本 fiddle here .
转换器将 Vector2
序列化为具有 X
和 Y
属性的对象,但您也可以将其序列化为具有两个值的数组如果你更喜欢。我不建议将序列化为原语 string
,因为 Vector2
不对应于 JSON 原语。
使用 custom contract resolver它不会为应用了 TypeConverter
的类型创建原始契约,例如 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没有提及使用这种格式时是否应保留零号。
因此,在这种情况下,往返 float
可能会导致二进制更改。
顺便说一句,Json.NET 在编写 double
时也使用 "R"
(如 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);
}
对于double
only,这种格式被记录为可能会丢失精度。来自 The Round-trip ("R") Format Specifier :
In some cases, Double values formatted with the "R" standard numeric format string do not successfully round-trip if compiled using the
/platform:x64
or/platform:anycpu
switches and run on 64-bit systems.
因此,通过 Json.NET 往返 double
可能会导致较小的二进制差异。但是,这并不严格适用于这里的问题,它专门针对 float
。
关于c# - 在不更改目标类型的情况下以最高精度序列化 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51703481/
我创建了一个基于命令行可移植脚本的工业化不可知构建系统,可用于快速构建多个依赖项目,而不必依赖特定的 IDE 或构建工厂。它是不可知的,因为它不是基于单个构建引擎。我使用 cmake 创建了第一个版本
我最初使用 Java 目标开发了一个语法(用于 TestRig 支持),然后将其移植到 Python(从 git hub 语法存储库扩展了 Python3 语法,因此需要将操作移植到 Python
我有一个以 iPhone 和 watchOS 为目标的 Xcode 项目。 iPhone 目标使用加速度计,模拟器不支持。我可以只启动 iPhone 应用程序而不启动 watch 目标吗?我从: Ca
您好,我想创建一个批处理文件,用于在 .eml 文件(目标 A)中查找某些关键字,然后删除它们所在的行。之后,我需要批处理文件将"new"文件放入(目标 B)中的单独 .eml 文件中。文件也可以是
当尝试通过 IntelliJ 运行示例 CorDapp (GitHub CorDapp) 时,我收到以下错误: Cannot inline bytecode built with JVM target
我在尝试向我的 kotlin spring 项目添加一些依赖项时遇到问题。我使用 spring boot 初始化程序来运行一个基本项目。 我的问题:如果我取消对 jackson 或 Koin 依赖项的
这是有问题的网站: http://www.onepixelroom.com/londonrefurb 当我点击关于部分后面的多个圆圈时,我希望它更改上面文本中的引号。 到目前为止,我得到它来显示 文本
单击后,我将删除两个元素 $(this) 和 $("#foo")。 目前我的代码如下所示: $(this).remove(); $("#foo").remove(); 如何在不重复自己的情况下优化它?
我有一个小脚本,可将 Markdown 文件编译为 html,并将其与一些样式表和 javascript 一起插入到模板的主体中。我有一个 GNU makefile 来完成这个: output.htm
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
一些背景知识: 在android中我们开发了同样的应用,基本上我们先开发了Android应用,现在我们创建了它的IOS版本,所以这个应用有多个客户端。在 android 中,我们实际上是使用 Andr
我想知道是否可以使用 knockout 来更改html中的目标() 我的所有其他信息都在 JavaScript 中,所以这对我来说是一个大问题。这是我的 JavaScript: var library
这个问题在这里已经有了答案: Selecting and manipulating CSS pseudo-elements such as ::before and ::after using j
我在我的有向图中添加了一堆节点和顶点,使用设置 typedef boost::adjacency_list graph; 创建 Node有一个节点名称字符串,Edge它的分数有一个整数。我试图遍历所有
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
如何存储我在 NSUserDefaults 中创建的 Goal 类型的对象数组? ( swift ) 代码如下: func saveGoalList ( newGoalList : [Goal] ){
Array.prototype.indexOf 和 Date.now 已在 ES5 中引入。如果我编译存储在文件 test.ts 中的以下代码,为什么 Typescript 不能转译? Date.no
我正在阅读有关属性的内容,并了解到可以使用您的代码将它们应用于不同的目标实体 -(请参阅 Attribute Targets)。 因此,查看我项目中的 AssemblyInfo.cs 文件,我可以看到
给定一个 Makefile: all: build/a build/b build/c # need to change this to all: build/* build/a:
我有一个带有多框架目标的项目- netstandard2.0;net471 . 我想为 netframework 构建解决方案和 netstandard分别。 目前我使用这个 MSBuild 命令:
我是一名优秀的程序员,十分优秀!