为什么DataContractJsonSerializer和toSource产生不同的结果?

时间:2011-10-14 13:25:25

标签: c# javascript asp.net-mvc-3

我需要将javascript对象传递给ASP.NET MVC,我想这样做:

var p = { account:'123', page:'item' }; 
var message = escape(p.toSource());
// pass message to action method

产生类似这样的东西(未转义为可读性):

({account:"123", page:"item"})

在ASP.NET MVC中,我试图反序列化它并失败。 首先,DataContractJsonSerializer抱怨括号,没问题,在传递之前删除:

{account:"123", page:"item"}

然后它抱怨而不是“,所以我试图使用它来序列化datacontract,并得到:

{"account":"123", "page":"item"}

所以,问题是,我可以在ASP.NET MVC中使用某些东西,它可以使用javascripts toSource格式,还是我从头开始做错了?

3 个答案:

答案 0 :(得分:3)

  

所以,问题是,我可以在ASP.NET MVC中使用某些东西吗?   使用javascripts toSource格式,还是我从头开始做错了?

DataContractJsonSerializer类在JSON格式方面非常严格,并且符合规范。例如:

{account:"123", page:"item"}
根据规范,

无效的JSON 。您必须在属性名称周围加上双引号。您可以使用JSON.stringify来生成有效的JSON:

var p = { account:'123', page:'item' }; 
var message = JSON.stringify(p);

将生成{"account":"123","page":"item"},现在是有效的JSON。 JSON.stringify功能本身内置于现代浏览器中,如果您想支持旧版浏览器,则可以在页面中加入json2.js

话虽这么说,你可以使用不太严格的JavaScriptSerializer类,或者Json.NET来接受你的无效JSON字符串:

public class MyModel
{
    public string Account { get; set; }
    public string Page { get; set; }
}

class Program
{
    static void Main()
    {
        var json = "{account:\"123\", page:\"item\"}";
        var serializer = new JavaScriptSerializer();
        var model = serializer.Deserialize<MyModel>(json);
        Console.WriteLine("account = {0}, page = {1}", model.Account, model.Page);
    }
}

这就是说我不知道​​你为什么要手动反序列化JSON而不是依赖内置的JsonValueProviderFactory

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    ...
}

并使用AJAX从javascript调用:

$.ajax({
    url: '@Url.Action("MyAction", "Home")',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ account: "123", page: "item" }),
    success: function(result) {
        // TODO: process the results
    }
});

请注意,现在您现在需要担心任何手动序列化/反序列化。一切都由框架为您处理。

答案 1 :(得分:1)

.toSource()方法不返回JSON。在您的情况下,对象的有效JSON表示形式为:

{"account": 123, "page": "item"}

.toSource()返回的格式在MDN documentation中解释。

要在JavaScript中序列化对象,我建议使用第三方库以获得最大的兼容性。具体来说,您可以使用json2.js。但是,如果您使用的是现代浏览器,则还可以使用新JSON object.stringify()方法。但是,最通用的方法是第三方库。

答案 2 :(得分:0)

如果有人需要,我就这样做了:

function getSource(o) { var r = [], t; for (var i in o) if (o.hasOwnProperty(i)) { t = i + "~~" + "'" + o[i] + "'"; r.push(t); }; return r.join(); }        

请注意,它与原始toSource()有几个限制/差异:

a)我传递的模型总是平坦的,这意味着所有属性都被假定为字符串,如果模型具有复杂属性,则需要更改代码以使用递归来表示复杂属性。
b)我使用单引号,而原始toSource使用双引号 c)我正在将“:”替换为“~~”,因为即使编码它也会破坏网址,因此在服务器端序列化之前,需要进行替换。
d)原始的toSource返回结果,我不需要,所以我的函数返回没有它们的结果。