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

时间:2015-03-12 12:17:29

标签: c# json serialization json.net

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

Json.net无法支持的一件事是,如果您在int字段中存储floatdecimalobject。 e.g。

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

如果我在Something字段中存储intfloatdecimal,则会将其反序列化为longdouble(如json.net除了猜测json中基元的类型之外什么也做不了(“foo”:123< - int或long?)

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

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

我目前的方法是自定义JsonConverter,它处理上述类型,然后将它们序列化为代理类型,它将值保存为字符串,并将此类型的判别符保存。 然后在ReadJson上我把它转回正确的类型。

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

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

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

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

[编辑]

普通Json:

{
    "foo":123
}

VS

我们目前的代理版本:

{
    "foo": {
                  "$type":"Akka.Serialization.PrimitiveSurrogate, Akka",
                  "V":"123",
                  "T":1
             }
}

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

但是,仍然没有摆脱代理人本身的$类型,我想至少将其缩短为“$ type”:“代理” 或那个方向的东西。

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

{"$type":"Akka.Util.PrimitiveSurrogate, Akka","V":"F123.456"}

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

[再次编辑]

我现在已经明白了这一点:

{"$":"M123.456"}

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

1 个答案:

答案 0 :(得分:4)

有效载荷的大小有多重要?例如,您可以嵌入有关每个基元类型的元数据,实质​​上是将数据合同与数据捆绑在一起。 E.g:

{
    "someInteger": 123,
    "$someInteger.clrType": " System.Int32"
}

修改

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

{
  "someInteger.i": 123
}

这会将有效负载增加降低到每个原始值两个字符。我很确定这个点可以安全地用作分隔符;即,CLR标识符不应该具有标识符“someInteger.i”,尽管我会根据规范对此进行仔细检查(CLR中允许的标识符字符由以下文档管理,附件7 {{3} })。

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