4

我不知道为什么我现在才第一次注意到这种行为。希望确认这是否是设计行为,或者我是否遗漏了什么。

假设我有一个实现IEnumerable<T>并提供附加属性的视图模型。例如:

public class MyResultsViewModel : IEnumerable<MyResultViewModel>
{
    public IEnumerable<MyResultViewModel> Results { get; set; }
    public string SomeAdditionalProperty { get; set; }

    public IEnumerator<MyResultViewModel> GetEnumerator()
    {
        return Results.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator; }
}

假设我还有一个控制器,它将这个模型作为 json 返回。例如:

public ActionResult MyResults()
{
    var entities = PrivateMethodToGetEntities();
    var models = Mapper.Map<MyResultsViewModel>(entities);
    models.SomeAdditionalProperty = "I want this in the JSON too";
    return Json(models, JsonRequestBehavior.AllowGet);
    // models now contains a populated Results as well as the add'l string prop
}

当我从客户端上的 JSON 请求返回结果时,它总是以数组的形式返回。例如:

$.get('/Path/To/MyResults')
.success(function (results) {
    alert(results.SomeAdditionalProperty); // this alerts 'undefined'
    alert(results.length); // this alerts the size / count of Results
    alert(results[0]); // this alerts object
    // inspecting results here shows that it is a pure array, with no add'l props
});

在我重构以使视图模型不实现之前IEnumerable<T>,我想确认这是设计使然,并且应该是可以预期的。我想这是有道理的,因为必须扩展 javascript 数组对象的原型以容纳其他属性。

更新:

我对视图模型进行了以下更改,以避免命名内部 enumerable Results

public class MyResultsViewModel : IEnumerable<MyResultViewModel>
{
    public IEnumerable<MyResultViewModel> NotNamedResults { get; set; }
    public string SomeAdditionalProperty { get; set; }

    public IEnumerator<MyResultViewModel> GetEnumerator()
    {
        return NotNamedResults.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator; }
}

通过此更改,行为仍然存在。alert(JSON.stringify(results))为我的枚举集合生成正常的数组语法MyResultViewModel

[{"ResultProp1":"A","ResultProp2":"AA","ResultProp3":"AAA"},{"ResultProp1":"B","ResultProp2":"BB","ResultProp3":"BBB "},{"ResultProp1":"C","ResultProp2":"CC","ResultProp3":"CCC"},{"ResultProp1":"D","ResultProp2":"DD","ResultProp3": "DDD"},{"ResultProp1":"E","ResultProp2":"EE","ResultProp3":"EEE"}]

JsonResult在控制器操作返回和调用 jquerysuccess函数之间,似乎仍然丢失了附加属性。

4

1 回答 1

4

对于实现 IEnumerable 的类,JavascriptSerializer唯一的序列化枚举项。它调用GetEnumerator()以获取要序列化的数据,忽略任何其他属性。这就是为什么Counta 的属性List<T>没有序列化,任何其他属性也不会序列化的原因。

原因是这种构造不能用json格式表示。要包含其他属性,序列化程序必须创建一个哈希对象而不是数组,但严格来说,哈希对象不是一个集合。(例外是键/值对类,如Dictionary,它们被序列化为哈希对象。但规则不变 - 只有枚举的字典条目被序列化)。

但是为什么要创建一个IEnumerable直接实现序列化为 json 的类而不是这样做呢?

 public class MyResultsViewModel {
     public IEnumerable<MyModel> Models{ get; set; }
     public String SomeAdditionalData { get; set; } 
 }
于 2012-08-10T20:35:22.860 回答