使用 Json.NET 代理 int、float 和 decimal
Posted
技术标签:
【中文标题】使用 Json.NET 代理 int、float 和 decimal【英文标题】:Surrogate int, float and decimal using Json.NET 【发布时间】:2015-05-14 14:21:11 【问题描述】:我们使用 Json.net 进行序列化。我们希望几乎任何类型的用户定义的类/消息都可以序列化。
Json.net 无法立即支持的一件事是,如果您在 object
字段中存储 int
、float
或 decimal
。
例如
public class SomeMessage
public object Something get;set;
如果我在Something字段中存储int
、float
或decimal
,它将被反序列化为long
或double
(因为json.net只能猜测json 中基元的类型(“foo”:123
我完全知道我可以在属性上使用正确的类型并设置各种提示。
但我想为任何随机类/消息解决这个问题。
我目前的方法是自定义 JsonConverter,它处理上述类型,然后将它们序列化为代理类型,该类型将值作为字符串保存,并区分这是什么类型。 然后在 ReadJson 上,我将其转回正确的类型。
这样做有很多过热。 特别是对于代理类型的类型名。 "foo.bar.baz.PrimitiveSurrogate, mylib"
我可以自定义这个类型名的存储方式吗? 例如如果我想为某些特定类型应用别名?
还有其他方法吗? 我可以将整个内容序列化为一个特殊的字符串,它会更小,但话又说回来,感觉很不确定。
那么,如果我想在存储在无类型结构中时保持原语的正确类型,我有哪些选择?
[编辑]
普通Json:
"foo":123
对比
我们当前的代理版本:
"foo":
"$type":"Akka.Serialization.PrimitiveSurrogate, Akka",
"V":"123",
"T":1
我可以只用 `"V":"123L" 替换 V 和 T 并解析后缀,因为我们只在该类型中存储 int、float 和 decimal,因此我们可以轻松获得硬编码的描述符。
但是,这仍然没有摆脱代理本身的 $type,我想至少将其缩短为类似 `"$type":"Surrogate" 或者那个方向的东西。
[再次编辑] 我把它归结为:
"$type":"Akka.Util.PrimitiveSurrogate, Akka","V":"F123.456"
但我真的很想摆脱长类型名并以某种方式替换为别名。
[再次编辑]
我现在明白了:
"$":"M123.456"
这已经足够好了。 我们不需要与任何其他 json 系统互操作,它只是我们两端的框架,所以即使它不漂亮,也可以使用。
【问题讨论】:
【参考方案1】:有效载荷的大小有多重要?例如,您可以嵌入关于每个原语类型的元数据,本质上是将数据合同与数据捆绑在一起。例如:
"someInteger": 123,
"$someInteger.clrType": " System.Int32"
编辑:
如果负载大小最重要,您可以执行以下操作:
"someInteger.i": 123
这会将有效负载增加到每个原始值两个字符。我很确定这个点可以安全地用作分隔符;即 CLR 标识符不应该具有标识符“someInteger.i”,尽管我会根据规范仔细检查这一点(CLR 中允许的标识符字符由以下文档管理,附件 7 http://www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers) .
如果您真的想压缩它,您可以删除分隔符 (.) 并在属性名称后加上一个 CLR 规范不允许的 Unicode 字符,以表示所需的原始类型。有点hacky,但它会减少另一个字节的有效负载。 ;-)
【讨论】:
我意识到这与您当前的方法非常相似,但如果我正确解释了您的问题,我看不出有任何解决方法。类型信息必须放在某个地方,如果您不想提示类型本身,那么除了序列化的有效负载本身之外还有什么地方? 是的,看看我的编辑,我已经添加了我们当前代理方法的输出。 首要任务是什么?有效载荷大小?便携性/兼容性?性能? 有效负载大小,也许可以通过使用 JObject 手动处理 json 并对其进行一些自定义检查来实现。 在这种情况下,我认为将类型信息嵌入到 JSON 键中可能是这样做的方法(请参阅我的上次编辑)。这样,您可以跳过值周围的引号,仅使用 1 或 2 个字符来表示类型。不是很便携,但可能是最紧凑的 JSON 解决方案。以上是关于使用 Json.NET 代理 int、float 和 decimal的主要内容,如果未能解决你的问题,请参考以下文章
使用字符串、int 数组反序列化 json - .net core C#