我们正在使用Json.net进行序列化。我们希望允许任何类型的用户定义的类/消息可序列化。
Json.net无法支持的一件事是,如果您在int
字段中存储float
,decimal
或object
。
e.g。
public class SomeMessage
{
public object Something {get;set;}
}
如果我在Something字段中存储int
,float
或decimal
,则会将其反序列化为long
或double
(如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系统互操作,它只是我们在两端的框架,所以即使它不漂亮,编制的格式也可以工作。
答案 0 :(得分:4)
有效载荷的大小有多重要?例如,您可以嵌入有关每个基元类型的元数据,实质上是将数据合同与数据捆绑在一起。 E.g:
{
"someInteger": 123,
"$someInteger.clrType": " System.Int32"
}
修改强>
如果有效负载大小最重要,您可以执行以下操作:
{
"someInteger.i": 123
}
这会将有效负载增加降低到每个原始值两个字符。我很确定这个点可以安全地用作分隔符;即,CLR标识符不应该具有标识符“someInteger.i”,尽管我会根据规范对此进行仔细检查(CLR中允许的标识符字符由以下文档管理,附件7 {{3} })。
如果你真的想要压缩它,可以删除分隔符(。)并使用CLR规范不允许的单个Unicode字符后缀属性名称,以表示所需的基本类型。有点hacky,但它会减少另一个字节的有效负载。 ; - )