我的web api中有以下方法
public void Put(string id, [FromBody]IContent value) {
//Do stuff
}
我正在使用骨干js使用fiddler将以下JSON发送到服务器,值为null:
{
"id": "articles/1",
"heading": "Bar",
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"
}
但是如果我首先在JSON对象中添加$ type属性,则反序列化工作正常,请参阅:
{
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
"id": "articles/1",
"heading": "Bar"
}
是否可以配置newtonsoft以检查对象中任何位置的$ type属性而不是第一个属性,还是可以配置骨干,以便它始终首先在JSON对象中添加$type
属性?
答案 0 :(得分:4)
我强烈建议不要配置任何序列化程序(包括JSON.NET)来从传入的有效负载中读取对象类型。这在历史上一直是Web应用程序中存在大量漏洞的原因。相反,将公共入口点更改为您的操作以将实际类型作为绑定参数,然后根据需要委托给内部可测试方法。
答案 1 :(得分:3)
首先,AFAIK,Json.NET的代码经过优化,以避免将整个对象保存在内存中,只是为了读取它的类型。因此,最好将$type
作为第一个属性。
其次,您可以编写自己的JsonConverter
,首先读取JObject
(使用Load
方法),手动读取$type
属性,从序列化程序的{{1获取类型,创建值并从SerializationBinder
填充它。
第三,关于安全性。虽然Json.NET的JObject
可能听起来不错,但通常不是。它允许Json.NET通过在JSON文件中编写其类型,从任何程序集创建任何对象类型。最好将自定义$type
与字典一起使用,该字典只允许您指定的类型。您可以在我的私有框架中找到一个示例(它还支持从SerializationBinder
获取$type
的值):
(这个版本使用了其他类中的一些方法,但它们很简单。后来的提交使得类更复杂。)
答案 2 :(得分:1)
这将在骨干网中起作用,但我不知道每个浏览器的行为是否相同。基本上,并不能保证每个浏览器都会按照添加的顺序保留项目。
MyModel = Backbone.Model.extend({
// ...
toJSON: function(){
// build the "$type" as the first parameter
var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
// get the rest of the data
_.extend(json, Backbone.Model.prototype.toJSON.call(this));
// send it back, and hope it's in the right order
return json;
}
});
你最好让NewtonSoft的JSON解串器工作,而不需要它在特定的位置。希望这是可能的。
答案 3 :(得分:1)
我显然有同样的问题,有人找到答案。不确定分享答案并给予他所有信用的适当方式,但这是链接: Newtonsoft JSON.net deserialization error where fields in JSON change order