2013-02-22 64 views
0

我一直在试图找出为什么我的一些测试没有工作(TDD),并设法追踪到一个类的序列化,但我不知道为什么它不工作。有两种风格,一种简单的版本和一种更复杂的版本,稍微复杂一些涉及在Parameter.Value中有一组值。JavaScriptSerializer和MVC - 与JSON挣扎

简单的版本,我有一个类,可以使用JavaScriptSerializer(我假设这是MVC如何生成JSON时的工作方式)serailzied。它产生的结构是这样的:

{ 
    "Name": "TestQuery", 
    "QueryId": 1, 
    "Parameters": [ 
    { 
     "Name": "MyString", 
     "DataType": 0, 
     "Value": "A String", 
     "IsArray": false 
    }], 
    "Sql": "SELECT * FROM Queries" 
} 

有3个C#类QueryParameterCollection(其为KeyedCollection<String, Parameter>)和Parameter。所有这些都被标记为DataContract/DataMember属性,并通过DataContractSerializer序列化没有任何问题。

然而,JavaScriptSerializer,正确地将对象序列化到上面的JSON,但在反序列化时,我没有参数,他们似乎错过了。

有没有人有任何想法,为什么这些失败,我可以做些什么来解决它?

回答

1

为什么KeyedCollection<String, Parameter>?你有一个数组,而不是字典,所以你的JSON应符合以下结构:

public class Query 
{ 
    public int QueryId { get; set; } 
    public string Name { get; set; } 
    public string Sql { get; set; } 
    public Parameter[] Parameters { get; set; } 
} 

public class Parameter 
{ 
    public string Name { get; set; } 
    public int DataType { get; set; } 
    public string Value { get; set; } 
    public bool IsArray { get; set; } 
} 

,然后你就可以反序列化没有任何问题:

var serializer = new JavaScriptSerializer(); 
var json = @" 
{ 
    ""Name"": ""TestQuery"", 
    ""QueryId"": 1, 
    ""Parameters"": [ 
    { 
     ""Name"": ""MyString"", 
     ""DataType"": 0, 
     ""Value"": ""A String"", 
     ""IsArray"": false 
    }], 
    ""Sql"": ""SELECT * FROM Queries"" 
}"; 
var query = serializer.Deserialize<Query>(json); 

您也可以摆脱[Data*]属性来自您的视图模型,它们不被JavaScriptSerializer类使用。

+0

我选择了一个KeyedCollection,因为所有参数都需要唯一命名,而且我想通过后面的Named查找来访问它们,所以它看起来很有意义。 – Ian 2013-02-22 09:31:55

+1

那么,你可以在你的域模型中使用KeyedCollections,但是在你的视图模型中(这是你的JSON反序列化),你不应该这样做。序列化程序不可能知道什么是你的字典的关键。如果你想达到这个目标,你将不得不编写自定义的json转换器。但恕我直言,你不应该为此烦恼。 – 2013-02-22 09:34:51