使用 Json.NET 替代整数、浮点数和小数

Surrogate int, float and decimal using Json.NET

我们正在使用 Json.net 进行序列化。我们希望允许几乎任何类型的用户定义 class/message 可序列化。

如果您在 object 字段中存储 intfloatdecimal,则 Json.net 无法立即支持的一件事. 例如

 public class SomeMessage
 {
      public object Something {get;set;}
 }

如果我在 Something 字段中存储 intfloatdecimal,它将被反序列化为 longdouble (因为 json.net 只能猜测 json 中的基元类型("foo":123 <- int 或 long?)

我完全知道我可以在 属性 上使用正确的类型并设置各种提示。

但我想随机解决这个问题class/message。

我目前的方法是使用自定义 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 系统互操作,它只是我们两端的框架,所以即使它不漂亮,组成的格式也能工作。

有效负载的大小有多重要?例如,您可以嵌入有关每个原语类型的元数据,本质上是将数据契约与数据捆绑在一起。例如:

{
    "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,但它会减少另一个字节的有效负载。 ;-)