使用Json.NET代理int,float和decimal

Rog*_*son 6 c# serialization json json.net

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

这Json.net不能支持开箱即用的一件事是,如果你存储的int,floatdecimalobject现场.例如

 public class SomeMessage
 {
      public object Something {get;set;}
 }
Run Code Online (Sandbox Code Playgroud)

如果我存储一个int,float或者decimal在Something字段中,它将被反序列化为a long或a double(因为json.net除了猜测json中基元的类型之外不能做任何事情("foo":123 < - int或长?)

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

但是我想为任何随机类/消息解决这个问题.

我目前的方法是一个自定义的JsonConverter,它处理上面的类型,然后将它们序列化为代理类型,它将值保存为字符串,并将其作为类型的鉴别器.然后在ReadJson上我将其转回正确的类型.

这样做有很多过热.特别是对于代理类型的类型名称."foo.bar.baz.PrimitiveSurrogate,mylib"

我可以自定义此typename的存储方式吗?例如,如果我想将别名应用于某些特定类型?

还有其他方法吗?我可以将整个事物序列化为一个特殊的字符串,它会更小,但是再一次,感觉就好了.

那么,如果我想在存储在无类型结构中时保持基元的正确类型,我有什么选择呢?

[编辑]

普通Json:

{
    "foo":123
}
Run Code Online (Sandbox Code Playgroud)

我们目前的代理版本:

{
    "foo": {
                  "$type":"Akka.Serialization.PrimitiveSurrogate, Akka",
                  "V":"123",
                  "T":1
             }
}
Run Code Online (Sandbox Code Playgroud)

我可以用"V"代替V和T:"123L"并解析后缀,因为我们只存储该类型的int,float和decimal,所以我们可以很容易地得到一个硬编码的描述符.

但是,这仍然没有摆脱代理人本身的$类型,我想至少缩短到类似"$ type":"代理"或者那个方向的东西.

[再次编辑]我已经把它归结为:

{"$type":"Akka.Util.PrimitiveSurrogate, Akka","V":"F123.456"}
Run Code Online (Sandbox Code Playgroud)

但我真的想摆脱长名字,并以某种方式替换别名.

[再次编辑]

我现在已经明白了:

{"$":"M123.456"}
Run Code Online (Sandbox Code Playgroud)

那个好的imo.我们不需要与任何其他json系统互操作,它只是我们在两端的框架,所以即使它不漂亮,编写的格式也可以工作.

Chr*_*rna 4

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

{
    "someInteger": 123,
    "$someInteger.clrType": " System.Int32"
}
Run Code Online (Sandbox Code Playgroud)

编辑:

如果有效负载大小最重要,您可以执行以下操作:

{
  "someInteger.i": 123
}
Run Code Online (Sandbox Code Playgroud)

这会将有效负载增加减少到每个原始值两个字符。我很确定这个点可以安全地用作分隔符;即 CLR 标识符不可能具有标识符“someInteger.i”,尽管我会根据规范仔细检查这一点(CLR 中允许的标识符字符由以下文档附件 7 http: // www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers)。

如果您确实想压缩它,可以删除分隔符 (.) 并在属性名称后面添加 CLR 规范不允许的单个 Unicode 字符,以表示所需的基本类型。有点 hacky,但它会减少另一个字节的有效负载。;-)