通过将Json.net
设置为TypeNameHandling
在TypeNameHandling.Objects
中实现了我正在做的事情。这样,对象类型也将被序列化,反序列化的对象将具有确切的原始类型。
但是,使用TypeNameHandling
会带来一些安全问题,并且要求我们使用自定义SerializationBinder
来限制将支持的类型,以避免可能的代码注入。这不是我尝试寻找其他解决方案的主要原因。实际上,我发现使用TypeNameHandling.Objects
可以将一个对象序列化为一个复杂的JSON,不仅包括对象数据本身和对象类型,还包括一些对我来说似乎多余的属性。
我认为我们只需要再一个包含有关对象类型的信息的属性(例如对象类型的程序集限定名称),因此我想创建一个自定义JsonConverter
,它将把任何对象序列化为一些JSON,例如这个:
{
"Item" : "normal JSON string of object",
"ItemType" : "assembly qualified name of object type"
}
那还不够吗?正如我之前说过的,除了两个与(具有不同名称)相似的属性外,Json.net
库还包含其他一些属性(签名...),这些属性对我来说真的很多余。
我并没有要求如何实现上面提到的自定义JsonConverter
。我只是想知道该转换器(具有简化的JSON结构)是否还可以,还是应该使用Json.net
和TypeNameHandling
提供的标准解决方案(涉及更复杂的JSON结构)?我主要担心的是由于要转换/序列化/传输的数据更多,TypeNameHandling
设置为Objects
时可能会出现性能问题。
与标准解决方案有关的另一个问题是性能问题,实际上我只需要将自定义转换逻辑应用于确切类型为object
的所有对象,而不是应用于所有其他强类型对象(可能仍然不必要)由TypeNameHandling
申请?)
答案 0 :(得分:1)
我对您为多态自定义JsonConverter
提出的设计有一些反应(我们将其命名为PolymorphicConverter<T>
,其中T
是基本类型)
关于安全性,您写道,
...使用
TypeNameHandling
会暴露一些安全问题,并要求我们使用自定义SerializationBinder
来限制将支持的类型,以避免可能的代码注入。
TypeNameHandling
也将产生与PolymorphicConverter<T>
相同的安全风险。
这里的风险是,攻击者欺骗了一些多态反序列化代码以实例化攻击小工具。有关示例和讨论,请参见TypeNameHandling caution in Newtonsoft Json和External json vulnerable because of Json.Net TypeNameHandling auto?。如果攻击者使用转换器支持的"ItemType"
属性中指定的攻击工具类型来制作JSON,则最终可能会实例化攻击工具并实施攻击。
您可以通过仅对那些实际上是多态的属性应用PolymorphicConverter<T>
(或[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
)来为已知的多态属性或数组项启用多态反序列化支持,从而减少攻击面练习-但是,如果这些属性的多态基本类型恰好与攻击小工具兼容,那么您将很容易受到攻击。
因此,无论使用哪种机制,无论如何在JSON中对类型信息进行编码的细节,您仍将需要诸如定制SerializationBinder
之类的东西来过滤掉顽皮的类型。
JSON文件大小。 Json.NET通过在对象的开头添加一个属性来对类型信息进行编码:
"$type" : "assembly qualified name of object type"
您的计划是添加:
"ItemType" : "assembly qualified name of object type"
除非您的类型名称更紧凑,否则尚不清楚为什么会有优势。
性能。您写道,
我主要担心的是由于要转换/序列化/传输的数据更多,
TypeNameHandling
设置为Objects
时可能会出现性能问题。
首先,为什么不仅仅进行测量和发现?参见https://ericlippert.com/2012/12/17/performance-rant/
第二,Newtonsoft有一个设置MetadataPropertyHandling
,当设置为Default
时,假定多态属性"$type"
首先出现在每个对象中,因此能够将它们流式传输到无需将整个JSON预先加载到JToken
层次结构中。
如果您的转换器无条件预加载到JToken
层次结构中以获取"ItemType"
属性的值,则其性能可能会变差。
关于将多态反序列化限制为仅必需的属性,您写道:
与标准解决方案有关的另一个问题是性能问题,实际上我只需要将自定义转换逻辑应用于确切类型为
object
的所有对象,而不是应用于所有其他强类型对象
无论哪种方式,custom ContractResolver
都可以实现。覆盖DefaultContractResolver.CreateProperty
,并在JsonProperty.PropertyType == typeof(object)
时根据需要设置TypeNameHandling
或Converter
,具体取决于您选择的解决方案。